├── .coveragerc ├── .devcontainer ├── alma9 │ ├── .bashrc │ ├── alma9-development.Containerfile │ ├── devcontainer.json │ └── requirements.txt └── centos7 │ ├── .bashrc │ ├── centos7-development.Containerfile │ ├── devcontainer.json │ └── requirements.txt ├── .fmf └── version ├── .github ├── CODEOWNERS ├── label-commenter-config.yml ├── pull_request_template.md ├── release.yml ├── renovate.json └── workflows │ ├── autotag.yml │ ├── build-rpm.yml │ ├── build_images.yml │ ├── codeql.yml │ ├── coverage.yml │ ├── enforce_labels.yml │ ├── generate_manpage.yml │ ├── jira-links.yml │ ├── label-commenter.yml │ ├── main-docs-deploy.yml │ ├── pr-docs-check.yml │ └── tests.yml ├── .gitignore ├── .gitleaks.toml ├── .packit.yaml ├── .pre-commit-config.yaml ├── .vscode └── extensions.json ├── CONTRIBUTING.md ├── Containerfiles ├── centos7.Containerfile ├── centos8.Containerfile └── centos9.Containerfile ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── config └── convert2rhel.ini ├── convert2rhel ├── __init__.py ├── actions │ ├── __init__.py │ ├── conversion │ │ ├── __init__.py │ │ ├── list_non_red_hat_pkgs_left.py │ │ ├── lock_releasever.py │ │ ├── pkg_manager_config.py │ │ ├── preserve_only_rhel_kernel.py │ │ ├── set_efi_config.py │ │ └── transaction.py │ ├── post_conversion │ │ ├── __init__.py │ │ ├── breadcrumbs_finish_collection.py │ │ ├── hostmetering.py │ │ ├── kernel_boot_files.py │ │ ├── modified_rpm_files_diff.py │ │ ├── remove_tmp_dir.py │ │ ├── rhsm_custom_facts_config.py │ │ └── update_grub.py │ ├── pre_ponr_changes │ │ ├── __init__.py │ │ ├── backup_system.py │ │ ├── custom_repos_are_valid.py │ │ ├── handle_packages.py │ │ ├── kernel_modules.py │ │ ├── special_cases.py │ │ ├── subscription.py │ │ └── transaction.py │ ├── report.py │ └── system_checks │ │ ├── __init__.py │ │ ├── check_firewalld_availability.py │ │ ├── convert2rhel_latest.py │ │ ├── dbus.py │ │ ├── duplicate_packages.py │ │ ├── efi.py │ │ ├── els.py │ │ ├── eus.py │ │ ├── grub_validity.py │ │ ├── is_loaded_kernel_latest.py │ │ ├── package_updates.py │ │ ├── readonly_mounts.py │ │ ├── rhel_compatible_kernel.py │ │ └── tainted_kmods.py ├── applock.py ├── backup │ ├── __init__.py │ ├── certs.py │ ├── files.py │ ├── packages.py │ └── subscription.py ├── breadcrumbs.py ├── checks.py ├── cli.py ├── data │ ├── 7 │ │ └── x86_64 │ │ │ ├── configs │ │ │ ├── centos-7-x86_64.cfg │ │ │ ├── oracle-7-x86_64.cfg │ │ │ └── scientific-7-x86_64.cfg │ │ │ └── rhel-certs │ │ │ └── 69.pem │ ├── 8 │ │ └── x86_64 │ │ │ ├── configs │ │ │ ├── almalinux-8-x86_64.cfg │ │ │ ├── centos-8-x86_64.cfg │ │ │ ├── oracle-8-x86_64.cfg │ │ │ └── rocky-8-x86_64.cfg │ │ │ └── rhel-certs │ │ │ └── 479.pem │ ├── 9 │ │ └── x86_64 │ │ │ ├── configs │ │ │ ├── almalinux-9-x86_64.cfg │ │ │ ├── centos-9-x86_64.cfg │ │ │ ├── oracle-9-x86_64.cfg │ │ │ └── rocky-9-x86_64.cfg │ │ │ └── rhel-certs │ │ │ └── 479.pem │ └── version-independent │ │ ├── GLOBAL_EULA_RHEL │ │ ├── gpg-keys │ │ └── RPM-GPG-KEY-redhat-release │ │ └── redhat-uep.pem ├── exceptions.py ├── grub.py ├── i18n.py ├── initialize.py ├── logger.py ├── main.py ├── phase.py ├── pkghandler.py ├── pkgmanager │ ├── __init__.py │ └── handlers │ │ ├── __init__.py │ │ ├── base.py │ │ ├── dnf │ │ ├── __init__.py │ │ └── callback.py │ │ └── yum │ │ ├── __init__.py │ │ └── callback.py ├── redhatrelease.py ├── repo.py ├── subscription.py ├── systeminfo.py ├── toolopts │ ├── __init__.py │ └── config.py ├── unit_tests │ ├── README.md │ ├── __init__.py │ ├── actions │ │ ├── __init__.py │ │ ├── actions_test.py │ │ ├── conversion │ │ │ ├── __init__.py │ │ │ ├── list_non_red_hat_pkgs_left_test.py │ │ │ ├── lock_releasever_test.py │ │ │ ├── pkg_manager_config_test.py │ │ │ ├── preserve_only_rhel_kernel_test.py │ │ │ ├── set_efi_config_test.py │ │ │ └── transaction_test.py │ │ ├── data │ │ │ ├── __init__.py │ │ │ ├── aliased_action_name │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ ├── extraneous_files │ │ │ │ ├── __init__.py │ │ │ │ ├── test.py │ │ │ │ └── test.txt │ │ │ ├── ignore__init__ │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ ├── multiple_actions_multiple_files │ │ │ │ ├── __init__.py │ │ │ │ ├── test1.py │ │ │ │ └── test2.py │ │ │ ├── multiple_actions_one_file │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ ├── not_action_itself │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ ├── only_subclasses_of_action │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ └── stage_tests │ │ │ │ ├── __init__.py │ │ │ │ ├── action_exceptions │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ │ ├── all_status_actions │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ │ ├── bad_deps1 │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ │ ├── deps_on_1 │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ │ ├── good_deps1 │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ │ │ └── good_deps_failed_actions │ │ │ │ ├── __init__.py │ │ │ │ └── test.py │ │ ├── post_conversion │ │ │ ├── __init__.py │ │ │ ├── breadcrumbs_finish_collection_test.py │ │ │ ├── hostmetering_test.py │ │ │ ├── kernel_boot_files_test.py │ │ │ ├── modified_rpm_files_diff_test.py │ │ │ ├── remove_tmp_dir_test.py │ │ │ ├── rhsm_custom_facts_config_test.py │ │ │ └── update_grub_test.py │ │ ├── pre_ponr_changes │ │ │ ├── __init__.py │ │ │ ├── backup_system_test.py │ │ │ ├── custom_repos_are_valid_test.py │ │ │ ├── handle_packages_test.py │ │ │ ├── kernel_modules_test.py │ │ │ ├── special_cases_test.py │ │ │ ├── subscription_test.py │ │ │ └── transaction_test.py │ │ ├── report_test.py │ │ └── system_checks │ │ │ ├── __init__.py │ │ │ ├── check_firewalld_availability_test.py │ │ │ ├── convert2rhel_latest_test.py │ │ │ ├── dbus_test.py │ │ │ ├── duplicate_packages_test.py │ │ │ ├── efi_test.py │ │ │ ├── els_test.py │ │ │ ├── eus_test.py │ │ │ ├── grub_validity_test.py │ │ │ ├── is_loaded_kernel_latest_test.py │ │ │ ├── package_updates_test.py │ │ │ ├── readonly_mounts_test.py │ │ │ ├── rhel_compatible_kernel_test.py │ │ │ └── tainted_kmods_test.py │ ├── applock_test.py │ ├── backup │ │ ├── __init__.py │ │ ├── backup_test.py │ │ ├── certs_test.py │ │ ├── files_test.py │ │ ├── packages_test.py │ │ └── subscription_test.py │ ├── breadcrumbs_test.py │ ├── checks_test.py │ ├── cli_test.py │ ├── conftest.py │ ├── dummy_file │ ├── example_test.py │ ├── grub_test.py │ ├── initialize_test.py │ ├── logger_test.py │ ├── main_test.py │ ├── other_test.py │ ├── pkghandler_test.py │ ├── pkgmanager │ │ ├── __init__.py │ │ ├── handlers │ │ │ ├── __init__.py │ │ │ ├── dnf │ │ │ │ ├── __init__.py │ │ │ │ ├── callback_test.py │ │ │ │ └── dnf_test.py │ │ │ └── yum │ │ │ │ ├── __init__.py │ │ │ │ ├── callback_test.py │ │ │ │ └── yum_test.py │ │ └── pkgmanager_test.py │ ├── pyproject.toml │ ├── redhatrelease_test.py │ ├── repo_test.py │ ├── subscription_test.py │ ├── systeminfo_test.py │ ├── toolopts │ │ ├── __init__.py │ │ ├── config_test.py │ │ └── toolopts_test.py │ └── utils │ │ ├── __init__.py │ │ ├── subscription_test.py │ │ └── utils_test.py └── utils │ ├── __init__.py │ ├── files.py │ ├── rpm.py │ └── subscription.py ├── docs ├── Makefile ├── requirements.txt └── source │ ├── _static │ └── .gitkeep │ ├── _templates │ ├── custom-class-template.rst │ └── custom-module-template.rst │ ├── actions.rst │ ├── all.rst │ ├── conf.py │ ├── index.rst │ ├── meta.rst │ └── pkgmanager.rst ├── man ├── __init__.py ├── convert2rhel.8 ├── distribution.man └── synopsis ├── packaging └── convert2rhel.spec ├── plans ├── main.fmf ├── stream.fmf ├── tier0.fmf └── tier1.fmf ├── pyproject.toml ├── pytest.ini ├── requirements ├── centos7.requirements.txt ├── centos8.requirements.txt └── centos9.requirements.txt ├── schemas ├── assessment-schema-1.0.json ├── assessment-schema-1.1.json └── assessment-schema-1.2.json ├── scripts ├── build_locally.sh ├── extract_version_from_rpm_spec.py ├── manpage_generation.sh └── whitelist.py ├── setup.py └── tests ├── ansible_collections ├── group_vars │ └── all.yml ├── main.yml └── roles │ ├── add-custom-repos │ ├── main.yml │ ├── rhel7-repos.yml │ ├── rhel8-eus-repos.yml │ ├── rhel8-repos.yml │ ├── rhel9-eus-repos.yml │ └── rhel9-repos.yml │ ├── get-test-vars │ └── tasks │ │ ├── get-test-vars.yml │ │ └── main.yml │ ├── grub-setup │ └── tasks │ │ ├── grub_setup.yml │ │ └── main.yml │ ├── hardcode-eus-version-repos │ └── tasks │ │ ├── alma-eus-repos.yml │ │ ├── main.yml │ │ └── rocky-eus-repos.yml │ ├── install-testing-deps │ └── tasks │ │ └── main.yml │ ├── oracle-linux-specific │ └── tasks │ │ ├── boot_standard_kernel.yml │ │ ├── main.yml │ │ └── stop_firewalld_workaround.yml │ ├── packaging │ └── tasks │ │ ├── build_rpm.yml │ │ ├── install_rpm_from_local_build.yml │ │ ├── install_rpm_from_url.yml │ │ └── main.yml │ ├── reboot │ └── main.yml │ ├── remove-tf-artifact-leftovers │ └── tasks │ │ ├── clean_up_el7.yml │ │ ├── clean_up_el8.yml │ │ └── main.yml │ ├── update-ca-trust │ └── tasks │ │ ├── main.yml │ │ └── update-ca-trust.yml │ └── update-system │ └── tasks │ ├── main.yml │ └── update-system.yml └── integration ├── README.md ├── common ├── checks-after-conversion │ ├── artifacts │ │ ├── c2r_facts_schema.json │ │ └── c2r_migration_results_schema.json │ ├── main.fmf │ ├── test_check_data_collection.py │ ├── test_delete_temp_folder.py │ ├── test_enabled_repositories.py │ ├── test_firewalld_errors.py │ ├── test_flag_system_as_converted.py │ ├── test_grub_default.py │ ├── test_logging_not_duplicated.py │ ├── test_release_version.py │ ├── test_rhel_kernel.py │ ├── test_rhel_subman.py │ ├── test_verify_strings_in_log.py │ ├── test_yum_check.py │ └── test_yum_check_update.py └── utils │ └── reboot-after-conversion │ ├── main.fmf │ └── test_reboot.py ├── conftest.py ├── main.fmf ├── pyproject.toml ├── test_helpers ├── __init__.py ├── checks_nondestructive.py ├── common_functions.py ├── satellite.py ├── shell.py ├── subscription_manager.py ├── vars.py └── workarounds.py ├── tier0 ├── destructive │ ├── conversion-method │ │ ├── main.fmf │ │ ├── test_activation_key.py │ │ ├── test_config_file.py │ │ ├── test_custom_repos.py │ │ ├── test_one_key_satellite.py │ │ ├── test_pre_registered.py │ │ ├── test_rhsm.py │ │ ├── test_rhsm_els.py │ │ ├── test_rhsm_eus.py │ │ └── test_satellite.py │ ├── isolated-system-conversion │ │ ├── main.fmf │ │ ├── prepare_system.py │ │ └── test_isolated_system_conversion.py │ ├── main.fmf │ ├── single-yum-transaction │ │ ├── install_dependency_packages.py │ │ ├── install_multilib_packages.py │ │ ├── install_ntp_and_remove_dependency.py │ │ ├── main.fmf │ │ ├── remove_excld_pkgs_from_config.py │ │ ├── test_check_for_latest_packages.py │ │ └── test_single_yum_transaction.py │ └── yum-distro-sync │ │ ├── add-extras-repo │ │ ├── centos7_extras.yml │ │ ├── centos8_extras.yml │ │ └── main.yml │ │ ├── install_problematic_package.py │ │ ├── main.fmf │ │ └── test_yum_distro_sync.py ├── main.fmf └── non-destructive │ ├── application-lock │ ├── main.fmf │ └── test_application_lock.py │ ├── assessment-report │ ├── main.fmf │ └── test_assessment_report.py │ ├── basic-sanity-checks │ ├── main.fmf │ └── test_basic_sanity_checks.py │ ├── config-file │ ├── main.fmf │ └── test_config_file.py │ ├── custom-repository │ ├── files │ │ ├── rhel7.repo │ │ ├── rhel8-eus.repo │ │ ├── rhel8.repo │ │ ├── rhel9-eus.repo │ │ └── rhel9.repo │ ├── main.fmf │ └── test_custom_repository.py │ ├── cve-2022-1662 │ ├── main.fmf │ └── test_cve-2022-1662.py │ ├── duplicate-pkgs │ ├── main.fmf │ └── test_duplicate_pkgs.py │ ├── els │ ├── main.fmf │ └── test_els_enablement.py │ ├── enabled-repositories-after-analysis │ ├── main.fmf │ └── test_enabled_repositories_after_analysis.py │ ├── eus │ ├── main.fmf │ └── test_eus_enablement.py │ ├── file-backup │ ├── main.fmf │ └── test_file_backup.py │ ├── firewalld-inhibitor │ ├── main.fmf │ └── test_firewalld_inhibitor.py │ ├── grub │ ├── main.fmf │ └── test_invalid_changed_to_grub.py │ ├── kernel-modules │ ├── files │ │ ├── Makefile │ │ └── my_kmod.c │ ├── main.fmf │ └── test_unsupported_kmod.py │ ├── kernel │ ├── files │ │ └── broken_repo.repo │ ├── main.fmf │ ├── test_custom_kernel.py │ ├── test_kernel_check_verification.py │ └── test_oracle_unsupported_uek.py │ ├── logged-command │ ├── main.fmf │ └── test_logged_command.py │ ├── main.fmf │ ├── modified-releasever │ ├── main.fmf │ └── test_modified_releasever.py │ ├── problematic-third-party-pkgs │ ├── main.fmf │ └── test_problematic_third_party_pkgs.py │ ├── rhsm-facts │ ├── main.fmf │ └── test_rhsm_facts_update_analysis.py │ ├── rollback-handling │ ├── main.fmf │ └── test_rollback_handling.py │ ├── single-yum-transaction-validation │ ├── main.fmf │ └── test_single_yum_transaction_validation.py │ ├── subscription-manager │ ├── main.fmf │ ├── test_sub_man_pre_register.py │ └── test_sub_man_rollback.py │ ├── system-release-backup │ ├── files │ │ ├── baseos.repo │ │ └── ubi.repo │ ├── main.fmf │ └── test_system_release_backup.py │ └── user-prompt-response │ ├── main.fmf │ └── test_user_prompt_response.py └── tier1 ├── destructive ├── changed-grub-file │ ├── main.fmf │ └── test_valid_changed_grub.py ├── changed-yum-conf │ ├── main.fmf │ └── test_patch_yum_conf.py ├── detect-bootloader-partition │ ├── main.fmf │ └── test_detect_correct_boot_partition.py ├── error-after-ponr │ ├── main.fmf │ └── test_error_after_ponr.py ├── excluded-packages-removed │ ├── main.fmf │ └── test_excluded_pkgs_removed.py ├── firewalld-disabled-ol8 │ ├── main.fmf │ └── test_firewalld_disabled_ol8.py ├── host-metering │ ├── main.fmf │ ├── test_host_metering_enabled.py │ └── test_run_conversion_with_metering.py ├── kernel-boot-files │ ├── main.fmf │ ├── test_handle_corrupted_files.py │ └── test_handle_missing_boot_files.py ├── kernel-check-skip │ ├── install_older_kernel.py │ ├── main.fmf │ └── test_latest_kernel_check_skip.py ├── kernel-core-only │ ├── main.fmf │ └── remove_kernel_pkg.py ├── main.fmf ├── multiple-nic │ ├── main.fmf │ └── multiple_nic.py ├── one-kernel-scenario │ ├── main.fmf │ └── test_one_kernel_scenario.py ├── os-release-removal │ ├── main.fmf │ └── remove_os_release.py ├── proxy-conversion │ ├── main.fmf │ └── test_proxy_conversion.py ├── set-locale │ └── use_non_english_language.py ├── system-not-up-to-date │ ├── main.fmf │ └── test_system_not_up_to_date.py ├── unavailable-package │ ├── ansible │ │ └── install_pkg_removed_from_centos_85_repos.yml │ ├── main.fmf │ └── test_pkg_removed_from_centos_85.py └── yum-conf-exclude-packages │ ├── main.fmf │ └── test_yum_conf_exclude_packages.py ├── main.fmf └── non-destructive ├── httpd-package-transaction-error ├── main.fmf └── test_httpd_package_transaction_error.py └── main.fmf /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = 4 | convert2rhel 5 | omit = 6 | convert2rhel/unit_tests/* 7 | 8 | [paths] 9 | source = 10 | convert2rhel/ 11 | 12 | [report] 13 | fail_under = 80 14 | skip_covered = True 15 | show_missing = True 16 | -------------------------------------------------------------------------------- /.devcontainer/alma9/.bashrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | alias python='python3' 4 | alias ll='ls -lh' 5 | alias la='ls -lah' 6 | alias cd..='cd ..' 7 | alias rm='rm -I' 8 | 9 | # set a fancy prompt (non-color, unless we know we "want" color) 10 | case "$TERM" in 11 | xterm-color|*-256color) color_prompt=yes;; 12 | esac 13 | PS1='\[\033[01;34m\]\u\[\033[38;5;124m\](container)\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' 14 | unset color_prompt force_color_prompt 15 | -------------------------------------------------------------------------------- /.devcontainer/alma9/alma9-development.Containerfile: -------------------------------------------------------------------------------- 1 | FROM almalinux:9 as base 2 | 3 | ENV PODMAN_USERNS=keep-id 4 | ENV PYTHON python3 5 | ENV PIP pip 6 | ENV PYTHONDONTWRITEBYTECODE 1 7 | 8 | ENV APP_DEV_DEPS ".devcontainer/alma9/requirements.txt" 9 | ENV APP_DOCS_DEPS "docs/requirements.txt" 10 | ENV APP_MAIN_DEPS \ 11 | python3 \ 12 | python3-pip \ 13 | python3-six \ 14 | python3-dbus \ 15 | python3-pexpect \ 16 | python3-dnf \ 17 | git \ 18 | man \ 19 | make 20 | 21 | ENV USERNAME=vscode 22 | ENV USER_UID=1000 23 | ENV USER_GID=$USER_UID 24 | 25 | WORKDIR /workspaces/convert2rhel 26 | 27 | FROM base as install_main_deps 28 | 29 | RUN dnf update -y && dnf install -y $APP_MAIN_DEPS && dnf clean all 30 | 31 | FROM install_main_deps as install_dev_deps 32 | 33 | COPY $APP_DEV_DEPS $APP_DEV_DEPS 34 | COPY $APP_DOCS_DEPS $APP_DOCS_DEPS 35 | RUN $PIP install -r $APP_DEV_DEPS -r $APP_DOCS_DEPS 36 | 37 | FROM install_dev_deps as install_application 38 | 39 | RUN groupadd --gid=$USER_GID -r $USERNAME && \ 40 | useradd --uid=$USER_UID --home /home/$USERNAME --gid=$USER_GID -m $USERNAME 41 | 42 | RUN chown -R $USERNAME:$USERNAME . 43 | COPY --chown=$USERNAME:$USERNAME . . 44 | 45 | COPY .devcontainer/alma9/.bashrc /home/$USERNAME 46 | USER $USERNAME:$USERNAME 47 | -------------------------------------------------------------------------------- /.devcontainer/alma9/requirements.txt: -------------------------------------------------------------------------------- 1 | pre-commit==4.2.0 2 | pytest==8.3.5 3 | pytest-cov==6.1.1 4 | coverage[toml]==7.8.0 5 | -------------------------------------------------------------------------------- /.devcontainer/centos7/.bashrc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | 3 | alias python='python2' 4 | alias ll='ls -lh' 5 | alias la='ls -lah' 6 | alias cd..='cd ..' 7 | alias rm='rm -I' 8 | 9 | # set a fancy prompt (non-color, unless we know we "want" color) 10 | case "$TERM" in 11 | xterm-color|*-256color) color_prompt=yes;; 12 | esac 13 | PS1='\[\033[01;34m\]\u\[\033[38;5;124m\](container)\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' 14 | unset color_prompt force_color_prompt 15 | -------------------------------------------------------------------------------- /.devcontainer/centos7/centos7-development.Containerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 as base 2 | 3 | ENV PODMAN_USERNS=keep-id 4 | ENV PYTHON python2 5 | ENV PIP pip 6 | ENV PYTHONDONTWRITEBYTECODE 1 7 | 8 | ENV URL_GET_PIP "https://bootstrap.pypa.io/pip/2.7/get-pip.py" 9 | ENV APP_DEV_DEPS "centos7/requirements.txt" 10 | ENV APP_MAIN_DEPS \ 11 | python2 \ 12 | python-six \ 13 | dbus-python \ 14 | pexpect \ 15 | git 16 | 17 | ENV USERNAME=vscode 18 | ENV USER_UID=1000 19 | ENV USER_GID=$USER_UID 20 | 21 | WORKDIR /workspaces/convert2rhel 22 | 23 | FROM base as install_main_deps 24 | 25 | RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && \ 26 | sed -i 's|#baseurl=http://mirror.centos.org|baseurl=https://vault.centos.org|g' /etc/yum.repos.d/CentOS-* 27 | 28 | RUN yum update -y && yum install -y $APP_MAIN_DEPS && yum clean all 29 | 30 | FROM install_main_deps as install_dev_deps 31 | COPY $APP_DEV_DEPS $APP_DEV_DEPS 32 | RUN curl $URL_GET_PIP | $PYTHON 33 | RUN $PIP install -r $APP_DEV_DEPS 34 | 35 | FROM install_dev_deps as install_application 36 | 37 | RUN groupadd --gid=$USER_GID -r $USERNAME && \ 38 | useradd --uid=$USER_UID --home /home/$USERNAME --gid=$USER_GID -m $USERNAME 39 | 40 | RUN chown -R $USERNAME:$USERNAME . 41 | COPY --chown=$USERNAME:$USERNAME . . 42 | 43 | COPY centos7/.bashrc /home/$USERNAME 44 | USER $USERNAME:$USERNAME 45 | -------------------------------------------------------------------------------- /.devcontainer/centos7/requirements.txt: -------------------------------------------------------------------------------- 1 | pre-commit==1.21.0 2 | pytest==4.6.11 3 | pathlib2==2.3.7.post1 4 | mock==3.0.5 5 | pytest-cov==2.12.1 6 | coverage[toml]==5.5 7 | -------------------------------------------------------------------------------- /.fmf/version: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This is a comment. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # These owners will be the default owners for everything in 5 | # the repo. Unless a later match takes precedence, 6 | # @global-owner1 and @global-owner2 will be requested for 7 | # review when someone opens a pull request. 8 | 9 | # If you would like to be the owner of something and you 10 | # are either a member or well-known contributor. Just 11 | # submit a PR to add yourself 12 | 13 | # Convert2RHEL codebase itself 14 | convert2rhel/ @oamg/convert2rhel-developers 15 | 16 | # Integration tests 17 | tests/ @oamg/conversions-qe 18 | plans/ @oamg/conversions-qe 19 | 20 | # Packaging 21 | packaging/ @Venefilyn @bocekm 22 | -------------------------------------------------------------------------------- /.github/label-commenter-config.yml: -------------------------------------------------------------------------------- 1 | comment: 2 | footer: "\ 3 | ---\n\n\ 4 | Comment generated by an automation." 5 | 6 | labels: 7 | - name: tests/tier0 8 | labeled: 9 | pr: 10 | body: /packit test --labels tier0 11 | 12 | - name: tests/tier1 13 | labeled: 14 | pr: 15 | body: /packit test --labels tier1 16 | 17 | - name: tests/all 18 | labeled: 19 | pr: 20 | body: /packit test 21 | 22 | - name: tests/skip 23 | labeled: 24 | pr: 25 | body: This PR does not require integration tests to be run. 26 | 27 | - name: tests/sanity 28 | labeled: 29 | pr: 30 | body: /packit test --labels sanity 31 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Jira Issues: 5 | 6 | 7 | - 8 | 9 | Checklist 10 | 11 | - [ ] PR has been tested manually in a VM (either author or reviewer) 12 | - [ ] Jira issue has been made public if possible 13 | - [ ] `[RHELC-]` or `[HMS-]` is part of the PR title 14 | - [ ] Label depicting the kind of PR it is 15 | - [ ] PR title explains the change from the user's point of view 16 | - [ ] Code and tests are documented properly 17 | - [ ] The commits are squashed to as few commits as possible (without losing data) 18 | - [ ] When merged: Jira issue has been updated to `Release Pending` if relevant 19 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - skip/changelog 5 | authors: 6 | - dependabot 7 | - pre-commit-ci 8 | - renovate 9 | categories: 10 | - title: Breaking Changes 🛠 11 | labels: 12 | - kind/breaking 13 | - breaking-change 14 | - title: Enhancements 🎉 15 | labels: 16 | - kind/feature 17 | - enhancement 18 | - title: Security Hardening 🔒 19 | labels: 20 | - kind/security 21 | - security-hardening 22 | - title: Bug Fixes 🐛 23 | labels: 24 | - kind/bug-fix 25 | - bug-fix 26 | - title: Test Coverage Enhancements 🔧 27 | labels: 28 | - kind/tests 29 | - test-coverage-enhancement 30 | - title: Other Changes 31 | labels: 32 | - "kind/*" 33 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "enabledManagers": [ 6 | "dockerfile", 7 | "pip_requirements", 8 | "github-actions" 9 | ], 10 | "ignorePaths": [ 11 | "**/*centos7*Containerfile", 12 | ".devcontainer/centos7/**" 13 | ], 14 | "labels": [ 15 | "kind/dependencies", 16 | "skip/changelog", 17 | "tests/skip" 18 | ], 19 | "packageRules": [ 20 | { 21 | "matchPackageNames": [ 22 | "pytest" 23 | ], 24 | "matchFiles": [ 25 | "requirements/centos8.requirements.txt" 26 | ], 27 | "allowedVersions": "<=7.0" 28 | }, 29 | { 30 | "matchPackageNames": [ 31 | "Sphinx" 32 | ], 33 | "matchFiles": [ 34 | "docs/requirements.txt" 35 | ], 36 | "allowedVersions": "<=7.4.7" 37 | }, 38 | { 39 | "matchPackageNames": [ 40 | "sphinx_autodoc_typehints" 41 | ], 42 | "matchFiles": [ 43 | "docs/requirements.txt" 44 | ], 45 | "allowedVersions": "<=2.3.0" 46 | } 47 | ], 48 | "dockerfile": { 49 | "fileMatch": [ 50 | "(^|/|\\.)Containerfile$", 51 | "(^|/)Containerfile[^/]*$" 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.github/workflows/autotag.yml: -------------------------------------------------------------------------------- 1 | name: Auto Tag 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "1 12 * * 5" 7 | 8 | jobs: 9 | tag: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Determine tag 19 | id: determine_tag 20 | run: | 21 | current_tag=$(git describe --tags --abbrev=0) 22 | echo "tag=${current_tag%%-*}-$(date +%s)" >> $GITHUB_OUTPUT 23 | 24 | - name: Push tag 25 | run: | 26 | git config --local user.email "actions@github.com" 27 | git config --local user.name "GitHub Actions" 28 | git tag ${{ steps.determine_tag.outputs.tag }} 29 | git push origin ${{ steps.determine_tag.outputs.tag }} 30 | -------------------------------------------------------------------------------- /.github/workflows/build_images.yml: -------------------------------------------------------------------------------- 1 | name: build_and_publish_images 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | 7 | jobs: 8 | build_and_publish: 9 | name: build-${{ matrix.el.distro }}${{ matrix.el.ver }} 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | el: 14 | - distro: centos 15 | ver: 7 16 | - distro: centos 17 | ver: 8 18 | - distro: centos 19 | ver: 9 20 | 21 | permissions: 22 | contents: read 23 | packages: write 24 | runs-on: ubuntu-24.04 25 | steps: 26 | - name: Checkout Code 27 | uses: actions/checkout@v4 28 | 29 | - name: Login to GitHub Container Registry 30 | uses: docker/login-action@v3 31 | with: 32 | registry: ghcr.io 33 | username: ${{ github.repository_owner }} 34 | password: ${{ secrets.GITHUB_TOKEN }} 35 | 36 | - name: Set up Docker Buildx 37 | uses: docker/setup-buildx-action@v3 38 | 39 | - name: Build image 40 | uses: docker/build-push-action@v6 41 | with: 42 | push: true 43 | context: . 44 | file: ./Containerfiles/${{ matrix.el.distro }}${{ matrix.el.ver }}.Containerfile 45 | tags: ghcr.io/${{ github.repository_owner }}/convert2rhel-${{ matrix.el.distro }}:${{ matrix.el.ver }} 46 | cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/convert2rhel-${{ matrix.el.distro }}:${{ matrix.el.ver }} 47 | cache-to: type=inline 48 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | schedule: 9 | - cron: "33 23 * * 0" 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [python] 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v3 31 | with: 32 | languages: ${{ matrix.language }} 33 | queries: +security-and-quality 34 | 35 | - name: Autobuild 36 | uses: github/codeql-action/autobuild@v3 37 | 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v3 40 | with: 41 | category: "/language:${{ matrix.language }}" 42 | -------------------------------------------------------------------------------- /.github/workflows/enforce_labels.yml: -------------------------------------------------------------------------------- 1 | name: Require PR labels 2 | 3 | on: 4 | pull_request: 5 | types: [opened, labeled, unlabeled, synchronize] 6 | jobs: 7 | require-type-label: 8 | if: ${{ !contains(fromJson('["dependabot", "pre-commit-ci", "renovate"]'), github.actor ) }} 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: mheap/github-action-required-labels@v5 12 | with: 13 | mode: exactly 14 | count: 1 15 | labels: "kind/.*" 16 | use_regex: true 17 | require-verification-label: 18 | if: ${{ !contains(fromJson('["dependabot", "pre-commit-ci", "renovate"]'), github.actor ) }} 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: mheap/github-action-required-labels@v5 22 | with: 23 | mode: exactly 24 | count: 1 25 | labels: "tests/.*" 26 | use_regex: true 27 | -------------------------------------------------------------------------------- /.github/workflows/generate_manpage.yml: -------------------------------------------------------------------------------- 1 | name: Generate Manpages 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | generate-manpages: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v4 15 | 16 | - name: Setup Python 17 | uses: actions/setup-python@v5 18 | with: 19 | python-version: 3.13 20 | 21 | - name: Install dependencies 22 | run: | 23 | pip install argparse-manpage six pexpect 24 | 25 | - name: Install python3-rpm and python3-dnf package with apt-get 26 | run: | 27 | sudo apt-get update 28 | sudo apt-get install -y python3-rpm python3-dnf 29 | 30 | - name: Generate Manpages 31 | run: | 32 | chmod +x scripts/manpage_generation.sh 33 | bash scripts/manpage_generation.sh 34 | -------------------------------------------------------------------------------- /.github/workflows/jira-links.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Handle release 3 | 4 | on: 5 | release: 6 | types: [published] 7 | 8 | jobs: 9 | update_jira_links: 10 | name: Update Jira links 11 | if: ${{ github.event_name == 'release' }} 12 | runs-on: ubuntu-latest 13 | env: 14 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 15 | GH_REPO: ${{ github.repository }} 16 | steps: 17 | - name: Get release content 18 | run: gh release view ${{github.ref_name}} --json body --jq '.body' > releaseBody.txt 19 | 20 | - name: Add Jira links 21 | shell: python 22 | run: | 23 | import re 24 | 25 | # RegEx explained 26 | # (?] Add the Jira key group 0, equivalent of \1 37 | # (https://issues.redhat.com/browse/\g<0>) Add the Jira key group 0, equivalent of \1, to end of URL 38 | body = regex.sub(r"[\g<0>](https://issues.redhat.com/browse/\g<0>)", data) 39 | f.write(body) 40 | f.truncate() 41 | 42 | - name: Update release body with Jira links 43 | run: gh release edit ${{github.ref_name}} --notes-file releaseBody.txt 44 | -------------------------------------------------------------------------------- /.github/workflows/label-commenter.yml: -------------------------------------------------------------------------------- 1 | name: Tests Label Commenter 2 | 3 | on: 4 | pull_request_target: 5 | types: [labeled, unlabeled] 6 | 7 | permissions: 8 | contents: read 9 | issues: write 10 | pull-requests: write 11 | 12 | jobs: 13 | comment: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | sparse-checkout: | 19 | .github/label-commenter-config.yml 20 | sparse-checkout-cone-mode: false 21 | - name: Label Commenter 22 | uses: peaceiris/actions-label-commenter@v1.10.0 23 | env: 24 | RUNNER_DEBUG: 1 25 | with: 26 | github_token: ${{ secrets.LABEL_COMMENTER }} 27 | -------------------------------------------------------------------------------- /.github/workflows/main-docs-deploy.yml: -------------------------------------------------------------------------------- 1 | name: "Documentation deployment" 2 | 3 | on: 4 | # Runs on pushes targeting the default branch 5 | push: 6 | branches: ["main"] 7 | 8 | # Allows you to run this workflow manually from the Actions tab 9 | workflow_dispatch: 10 | 11 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 12 | permissions: 13 | contents: read 14 | pages: write 15 | id-token: write 16 | 17 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 18 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 19 | concurrency: 20 | group: "pages" 21 | cancel-in-progress: false 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | - name: Setup Pages 34 | uses: actions/configure-pages@v5 35 | - name: Install system dependencies 36 | uses: awalsh128/cache-apt-pkgs-action@latest 37 | with: 38 | packages: python3-pytest python3-sphinx python3-sphinx-autodoc-typehints python3-pexpect python3-six python3-rpm python3-hawkey python3-dnf python3-dbus python3-pytest 39 | version: 1.0 40 | - name: Add /etc/system-release 41 | run: sudo touch /etc/system-release 42 | - name: Build Sphinx 43 | uses: rickstaa/sphinx-action@v1.0.0 44 | with: 45 | docs-folder: "docs/" 46 | - name: Upload artifact 47 | uses: actions/upload-pages-artifact@v3 48 | with: 49 | # Upload entire repository 50 | path: docs/build/html/ 51 | - name: Deploy to GitHub Pages 52 | id: deployment 53 | uses: actions/deploy-pages@v4 54 | -------------------------------------------------------------------------------- /.github/workflows/pr-docs-check.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Docs Check" 2 | on: 3 | - pull_request 4 | 5 | jobs: 6 | docs: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: ammaraskar/sphinx-action@dev 11 | with: 12 | docs-folder: "docs/" 13 | pre-build-command: "pip install -r docs/requirements.txt --force-reinstall" 14 | 15 | - uses: actions/upload-artifact@v4 16 | with: 17 | name: DocumentationHTML 18 | path: docs/build/html/ 19 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: unit_tests 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | testing: 11 | name: testing-${{ matrix.el.distro }}${{ matrix.el.ver }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | el: 16 | - distro: centos 17 | ver: 7 18 | - distro: centos 19 | ver: 8 20 | - distro: centos 21 | ver: 9 22 | 23 | runs-on: ubuntu-24.04 24 | steps: 25 | - name: Checkout Code 26 | uses: actions/checkout@v4 27 | 28 | - name: Set up Docker Buildx 29 | uses: docker/setup-buildx-action@v3 30 | 31 | - name: Login to GitHub Container Registry 32 | uses: docker/login-action@v3 33 | with: 34 | registry: ghcr.io 35 | username: ${{ github.actor }} 36 | password: ${{ secrets.GITHUB_TOKEN }} 37 | 38 | - name: Run command 39 | run: | 40 | make tests${{ matrix.el.ver }} BUILD_IMAGES=0 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | cover/ 2 | .coverage 3 | coverage.xml 4 | dist/ 5 | SRPMS/ 6 | *.egg-info/ 7 | .DS_Store 8 | *.pyc 9 | system_tests/vmdefs/centos*/.vagrant/ 10 | *.copr.conf 11 | .venv/* 12 | .build-image* 13 | .install 14 | .pre-commit 15 | .rpms/* 16 | .srpms/* 17 | .idea/ 18 | .cache/ 19 | .pytest_cache/* 20 | .mypy_cache/* 21 | TAGS 22 | .vscode/* 23 | !.vscode/extensions.json 24 | docs/build/* 25 | docs/source/_autosummary 26 | *.code-workspace 27 | -------------------------------------------------------------------------------- /.gitleaks.toml: -------------------------------------------------------------------------------- 1 | [allowlist] 2 | paths = [ 3 | "tests/integration/tier0/non-destructive/cve-2022-1662/test_cve-2022-1662.py", 4 | ] 5 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | minimum_pre_commit_version: "2.9.0" 2 | repos: 3 | - repo: https://github.com/astral-sh/ruff-pre-commit 4 | # Ruff version. 5 | rev: v0.7.3 6 | hooks: 7 | # Run the linter. 8 | - id: ruff 9 | args: [ --fix ] 10 | # Run the formatter. 11 | - id: ruff-format 12 | 13 | - repo: "https://github.com/pre-commit/pre-commit-hooks" 14 | rev: "v5.0.0" 15 | hooks: 16 | - id: "end-of-file-fixer" 17 | - id: "trailing-whitespace" 18 | - id: "check-toml" 19 | - id: "check-yaml" 20 | - id: "check-merge-conflict" 21 | - repo: "https://gitlab.com/bmares/check-json5" 22 | rev: "v1.0.0" 23 | hooks: 24 | - id: "check-json5" 25 | - repo: "https://github.com/teemtee/tmt.git" 26 | rev: "1.38.0" 27 | hooks: 28 | - id: "tmt-tests-lint" 29 | verbose: false 30 | files: ^(tests/|plans/) 31 | 32 | - repo: https://github.com/packit/pre-commit-hooks 33 | rev: v1.2.0 34 | hooks: 35 | - id: check-rebase 36 | args: 37 | - https://github.com/oamg/convert2rhel.git 38 | stages: [manual, pre-push] 39 | - repo: https://github.com/gitleaks/gitleaks 40 | rev: v8.21.2 41 | hooks: 42 | - id: gitleaks 43 | stages: [manual, pre-push] 44 | - repo: https://github.com/jendrikseipp/vulture 45 | rev: v2.13 46 | hooks: 47 | - id: vulture 48 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | // List of extensions which should be recommended for users of this workspace. 5 | "recommendations": [ 6 | "ms-python.python", 7 | "ms-vscode-remote.remote-containers", 8 | "github.vscode-pull-request-github", 9 | "eamodio.gitlens", 10 | "ms-python.isort", 11 | "github.vscode-github-actions", 12 | ], 13 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 14 | "unwantedRecommendations": [] 15 | } 16 | -------------------------------------------------------------------------------- /Containerfiles/centos7.Containerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 as base 2 | 3 | ENV PYTHON python2 4 | ENV PIP pip 5 | ENV PYTHONDONTWRITEBYTECODE 1 6 | 7 | ENV URL_GET_PIP "https://bootstrap.pypa.io/pip/2.7/get-pip.py" 8 | ENV APP_DEV_DEPS "requirements/centos7.requirements.txt" 9 | ENV APP_MAIN_DEPS \ 10 | python-six \ 11 | dbus-python \ 12 | pexpect \ 13 | git \ 14 | rpm-build \ 15 | rpmlint \ 16 | python-devel \ 17 | python-setuptools \ 18 | rpmdevtools 19 | 20 | WORKDIR /data 21 | 22 | FROM base as install_main_deps 23 | 24 | RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && \ 25 | sed -i 's|#baseurl=http://mirror.centos.org|baseurl=https://vault.centos.org|g' /etc/yum.repos.d/CentOS-* 26 | 27 | RUN yum update -y && yum install -y $APP_MAIN_DEPS && yum clean all 28 | 29 | FROM install_main_deps as install_dev_deps 30 | RUN curl $URL_GET_PIP | $PYTHON 31 | COPY $APP_DEV_DEPS $APP_DEV_DEPS 32 | RUN $PIP install -r $APP_DEV_DEPS 33 | 34 | FROM install_dev_deps as install_application 35 | RUN groupadd --gid=1000 -r app && \ 36 | useradd -r --uid=1000 --gid=1000 app 37 | RUN chown -R app:app . 38 | COPY --chown=app:app . . 39 | USER app:app 40 | -------------------------------------------------------------------------------- /Containerfiles/centos8.Containerfile: -------------------------------------------------------------------------------- 1 | FROM centos:8 as base 2 | 3 | ENV PYTHON python3 4 | ENV PIP pip3 5 | ENV PYTHONDONTWRITEBYTECODE 1 6 | 7 | ENV URL_GET_PIP "https://bootstrap.pypa.io/pip/3.6/get-pip.py" 8 | ENV APP_DEV_DEPS "requirements/centos8.requirements.txt" 9 | ENV APP_MAIN_DEPS \ 10 | python3 \ 11 | python3-six \ 12 | python3-dbus \ 13 | python3-pexpect \ 14 | git \ 15 | rpm-build \ 16 | rpmlint \ 17 | python3-devel \ 18 | rpmdevtools 19 | 20 | WORKDIR /data 21 | 22 | FROM base as install_main_deps 23 | 24 | RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-Linux-* && \ 25 | sed -i 's|#baseurl=http://mirror.centos.org|baseurl=https://vault.centos.org|g' /etc/yum.repos.d/CentOS-Linux-* 26 | 27 | RUN dnf update -y && dnf install -y $APP_MAIN_DEPS && dnf clean all 28 | 29 | FROM install_main_deps as install_dev_deps 30 | RUN curl $URL_GET_PIP | $PYTHON 31 | COPY $APP_DEV_DEPS $APP_DEV_DEPS 32 | RUN $PIP install -r $APP_DEV_DEPS 33 | 34 | FROM install_dev_deps as install_application 35 | RUN groupadd --gid=1000 -r app && \ 36 | useradd --uid=1000 --gid=1000 app 37 | RUN chown -R app:app . 38 | COPY --chown=app:app . . 39 | USER app:app 40 | -------------------------------------------------------------------------------- /Containerfiles/centos9.Containerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/centos/centos:stream9 as base 2 | 3 | ENV PYTHON python3 4 | ENV PIP pip3 5 | ENV PYTHONDONTWRITEBYTECODE 1 6 | 7 | ENV APP_DEV_DEPS "requirements/centos9.requirements.txt" 8 | ENV APP_DOCS_DEPS "docs/requirements.txt" 9 | ENV APP_MAIN_DEPS \ 10 | util-linux \ 11 | python3 \ 12 | python3-pip \ 13 | python3-six \ 14 | python3-dbus \ 15 | python3-pexpect \ 16 | git \ 17 | rpm-build \ 18 | rpmlint \ 19 | python3-devel \ 20 | rpmdevtools 21 | 22 | WORKDIR /data 23 | 24 | FROM base as install_main_deps 25 | 26 | RUN dnf update -y && dnf install -y $APP_MAIN_DEPS && dnf clean all 27 | 28 | FROM install_main_deps as install_dev_deps 29 | RUN curl $URL_GET_PIP | $PYTHON 30 | COPY $APP_DEV_DEPS $APP_DEV_DEPS 31 | COPY $APP_DOCS_DEPS $APP_DOCS_DEPS 32 | RUN $PIP install -r $APP_DEV_DEPS -r $APP_DOCS_DEPS 33 | 34 | FROM install_dev_deps as install_application 35 | RUN groupadd --gid=1000 -r app && \ 36 | useradd --uid=1000 --gid=1000 app 37 | RUN chown -R app:app . 38 | COPY --chown=app:app . . 39 | USER app:app 40 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include convert2rhel/data * 2 | include man/* 3 | include LICENSE 4 | include README.md 5 | include config/convert2rhel.ini 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Convert2RHEL 2 | 3 | Convert2RHEL is a tool to convert RHEL-like systems to their RHEL counterparts. For example, CentOS Linux 8 to Red Hat Enterprise Linux 8. 4 | 5 | ## Usage 6 | For details about the utility and its usage, consult one of the following sources: 7 | 8 | 1. [Converting from an RPM-based Linux distribution to RHEL](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html-single/converting_from_a_linux_distribution_to_rhel_using_the_convert2rhel_utility/index) 9 | 1. Run `man convert2rhel` once the utility is installed on your system 10 | 11 | ### Automation 12 | To convert to RHEL at scale you may want to use the Ansible roles available at [https://github.com/oamg/infra.convert2rhel](). 13 | 14 | ## Contributing 15 | 16 | Contributions are welcome. Take a look at [CONTRIBUTING.md](CONTRIBUTING.md) for more information on how to get started. 17 | 18 | ## Contact 19 | 20 | For questions, troubleshooting, bug reports and feature requests: 21 | 22 | * Create [an issue](https://github.com/oamg/convert2rhel/issues/new) here on GitHub. 23 | * Ask a question through [GitHub Discussions](https://github.com/oamg/convert2rhel/discussions). 24 | -------------------------------------------------------------------------------- /config/convert2rhel.ini: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # This file should be in mode 0600 3 | # Example of configuration file convert2rhel.ini for secrets. 4 | # Possible locations of this file: 5 | # 1) user specified and passed by -c, --config-file option; highest priority 6 | # 2) ~/.convert2rhel.ini; lower priority 7 | # 3) /etc/convert2rhel.ini; the lowest priority 8 | 9 | [subscription_manager] 10 | # username = 11 | # password = 12 | # activation_key = 13 | # org = 14 | 15 | [host_metering] 16 | # Possible values here are "auto" or "force" 17 | # configure_host_metering = "auto" 18 | 19 | [inhibitor_overrides] 20 | # incomplete_rollback = false 21 | # tainted_kernel_module_check_skip = false 22 | # allow_older_version = false 23 | # allow_unavailable_kmods = false 24 | # skip_kernel_currency_check = false 25 | -------------------------------------------------------------------------------- /convert2rhel/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | __version__ = "2.2.0" 3 | -------------------------------------------------------------------------------- /convert2rhel/actions/conversion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/convert2rhel/actions/conversion/__init__.py -------------------------------------------------------------------------------- /convert2rhel/actions/conversion/list_non_red_hat_pkgs_left.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2024 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | from convert2rhel import actions, logger 19 | from convert2rhel.pkghandler import get_installed_pkgs_w_different_key_id, print_pkg_info 20 | from convert2rhel.systeminfo import system_info 21 | 22 | 23 | loggerinst = logger.root_logger.getChild(__name__) 24 | 25 | 26 | class ListNonRedHatPkgsLeft(actions.Action): 27 | id = "LIST_NON_RED_HAT_PKGS_LEFT" 28 | dependencies = ("REMOVE_NON_RHEL_KERNELS",) 29 | 30 | def run(self): 31 | """List all the packages that have not been replaced by the 32 | Red Hat-signed ones during the conversion. 33 | """ 34 | super(ListNonRedHatPkgsLeft, self).run() 35 | loggerinst.task("List remaining non-Red Hat packages") 36 | 37 | loggerinst.info("Listing packages not signed by Red Hat") 38 | non_red_hat_pkgs = get_installed_pkgs_w_different_key_id(system_info.key_ids_rhel) 39 | if not non_red_hat_pkgs: 40 | loggerinst.info("All packages are now signed by Red Hat.") 41 | return 42 | 43 | loggerinst.info("The following packages were left unchanged.\n") 44 | print_pkg_info(non_red_hat_pkgs) 45 | -------------------------------------------------------------------------------- /convert2rhel/actions/conversion/pkg_manager_config.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2024 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | from convert2rhel import actions, redhatrelease 19 | from convert2rhel.logger import root_logger 20 | 21 | 22 | logger = root_logger.getChild(__name__) 23 | 24 | 25 | class ConfigurePkgManager(actions.Action): 26 | id = "CONFIGURE_PKG_MANAGER" 27 | dependencies = ("CONVERT_SYSTEM_PACKAGES",) 28 | 29 | def run(self): 30 | """ 31 | Check if the distroverpkg tag inside the package manager config has been modified before the conversion and if so 32 | comment it out and write to the file. 33 | """ 34 | super(ConfigurePkgManager, self).run() 35 | 36 | logger.task("Patch package manager configuration file") 37 | 38 | pmc = redhatrelease.PkgManagerConf() 39 | pmc.patch() 40 | -------------------------------------------------------------------------------- /convert2rhel/actions/conversion/transaction.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2024 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | 19 | from convert2rhel import actions, exceptions, pkgmanager 20 | from convert2rhel.logger import root_logger 21 | 22 | 23 | logger = root_logger.getChild(__name__) 24 | 25 | 26 | class ConvertSystemPackages(actions.Action): 27 | id = "CONVERT_SYSTEM_PACKAGES" 28 | 29 | def run(self): 30 | """Convert the system packages using either yum/dnf.""" 31 | super(ConvertSystemPackages, self).run() 32 | 33 | try: 34 | logger.task("Replace system packages") 35 | transaction_handler = pkgmanager.create_transaction_handler() 36 | transaction_handler.run_transaction() 37 | except exceptions.CriticalError as e: 38 | self.set_result( 39 | level="ERROR", 40 | id=e.id, 41 | title=e.title, 42 | description=e.description, 43 | diagnosis=e.diagnosis, 44 | remediations=e.remediations, 45 | variables=e.variables, 46 | ) 47 | -------------------------------------------------------------------------------- /convert2rhel/actions/post_conversion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/convert2rhel/actions/post_conversion/__init__.py -------------------------------------------------------------------------------- /convert2rhel/actions/post_conversion/breadcrumbs_finish_collection.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2024 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | import logging 19 | 20 | from convert2rhel import actions, breadcrumbs 21 | 22 | 23 | logger = logging.getLogger(__name__) 24 | 25 | 26 | class BreadcumbsFinishCollection(actions.Action): 27 | id = "BREADCRUMBS_FINISH_COLLECTION" 28 | dependencies = ( 29 | "KERNEL_BOOT_FILES", 30 | "UPDATE_GRUB", 31 | ) 32 | 33 | def run(self): 34 | super(BreadcumbsFinishCollection, self).run() 35 | 36 | logger.task("Update breadcrumbs") 37 | breadcrumbs.breadcrumbs.finish_collection(success=True) 38 | -------------------------------------------------------------------------------- /convert2rhel/actions/post_conversion/rhsm_custom_facts_config.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2023 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | import logging 19 | 20 | from convert2rhel import actions, subscription 21 | 22 | 23 | loggerinst = logging.getLogger(__name__) 24 | 25 | 26 | class RHSMCustomFactsConfig(actions.Action): 27 | id = "RHSM_CUSTOM_FACTS_CONFIG" 28 | 29 | dependencies = () 30 | 31 | def run(self): 32 | super(RHSMCustomFactsConfig, self).run() 33 | loggerinst.task("Update RHSM custom facts") 34 | ret_code, output = subscription.update_rhsm_custom_facts() 35 | 36 | if not output: 37 | return None 38 | 39 | if ret_code != 0: 40 | self.add_message( 41 | level="WARNING", 42 | id="FAILED_TO_UPDATE_RHSM_CUSTOM_FACTS", 43 | title="Failed to update RHSM custom facts", 44 | description="Failed to update the RHSM custom facts with return code: {0} and output: {1}.".format( 45 | ret_code, output 46 | ), 47 | ) 48 | -------------------------------------------------------------------------------- /convert2rhel/actions/pre_ponr_changes/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/actions/system_checks/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/actions/system_checks/dbus.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2016 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | 19 | from convert2rhel import actions, subscription 20 | from convert2rhel.logger import root_logger 21 | from convert2rhel.systeminfo import system_info 22 | 23 | 24 | logger = root_logger.getChild(__name__) 25 | 26 | 27 | class DbusIsRunning(actions.Action): 28 | id = "DBUS_IS_RUNNING" 29 | 30 | def run(self): 31 | """Error out if we need to register with rhsm and the dbus daemon is not running.""" 32 | super(DbusIsRunning, self).run() 33 | logger.task("Check that DBus Daemon is running") 34 | 35 | if not subscription.should_subscribe(): 36 | logger.info("Did not perform the check because we have been asked not to subscribe this system to RHSM.") 37 | return 38 | 39 | if system_info.dbus_running: 40 | logger.info("DBus Daemon is running") 41 | return 42 | 43 | self.set_result( 44 | level="ERROR", 45 | id="DBUS_DAEMON_NOT_RUNNING", 46 | title="Dbus daemon not running", 47 | description="The Dbus daemon is not running", 48 | diagnosis="Could not find a running DBus Daemon which is needed to register with subscription manager.", 49 | remediations="Please start dbus using `systemctl start dbus`", 50 | ) 51 | -------------------------------------------------------------------------------- /convert2rhel/actions/system_checks/grub_validity.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2024 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | from convert2rhel import actions, utils 19 | from convert2rhel.logger import root_logger 20 | 21 | 22 | logger = root_logger.getChild(__name__) 23 | 24 | 25 | class GrubValidity(actions.Action): 26 | id = "GRUB_VALIDITY" 27 | 28 | def run(self): 29 | """ 30 | Execute grub2-mkconfig and report an error if it fails to execute. A failure means that the grub file 31 | is invalid. 32 | """ 33 | super(GrubValidity, self).run() 34 | logger.task("Check if the grub file is valid") 35 | output, ret_code = utils.run_subprocess(["grub2-mkconfig"], print_output=False) 36 | 37 | if ret_code != 0: 38 | self.set_result( 39 | level="ERROR", 40 | id="INVALID_GRUB_FILE", 41 | title="Grub boot entry file is invalid", 42 | description="The grub file seems to be invalid leaving the system in a" 43 | " non-clean state and must be fixed before continuing the conversion" 44 | " to ensure a smooth process.", 45 | remediations="Check the grub file inside `/etc/default` directory and remove any " 46 | "misconfigurations, then re-run the conversion.", 47 | ) 48 | -------------------------------------------------------------------------------- /convert2rhel/data/version-independent/gpg-keys/RPM-GPG-KEY-redhat-release: -------------------------------------------------------------------------------- 1 | pub 4096R/FD431D51 2009-10-22 2 | Key fingerprint = 567E 347A D004 4ADE 55BA 8A5F 199E 2F91 FD43 1D51 3 | uid Red Hat, Inc. (release key 2) 4 | 5 | -----BEGIN PGP PUBLIC KEY BLOCK----- 6 | Version: GnuPG v2.0.22 (GNU/Linux) 7 | 8 | mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF 9 | 0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF 10 | 0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c 11 | u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh 12 | XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H 13 | 5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW 14 | 9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj 15 | /DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1 16 | PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY 17 | HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF 18 | buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB 19 | tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0 20 | LmNvbT6JAjYEEwEIACACGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUCSuBJPAAK 21 | CRAZni+R/UMdUfIkD/9m3HWv07uJG26R3KBexTo2FFu3rmZs+m2nfW8R3dBX+k0o 22 | AOFpgJCsNgKwU81LOPrkMN19G0+Yn/ZTCDD7cIQ7dhYuDyEX97xh4une/EhnnRuh 23 | ASzR+1xYbj/HcYZIL9kbslgpebMn+AhxbUTQF/mziug3hLidR9Bzvygq0Q09E11c 24 | OZL4BU6J2HqxL+9m2F+tnLdfhL7MsAq9nbmWAOpkbGefc5SXBSq0sWfwoes3X3yD 25 | Q8B5Xqr9AxABU7oUB+wRqvY69ZCxi/BhuuJCUxY89ZmwXfkVxeHl1tYfROUwOnJO 26 | GYSbI/o41KBK4DkIiDcT7QqvqvCyudnxZdBjL2QU6OrIJvWmKs319qSF9m3mXRSt 27 | ZzWtB89Pj5LZ6cdtuHvW9GO4qSoBLmAfB313pGkbgi1DE6tqCLHlA0yQ8zv99OWV 28 | cMDGmS7tVTZqfX1xQJ0N3bNORQNtikJC3G+zBCJzIeZleeDlMDQcww00yWU1oE7/ 29 | To2UmykMGc7o9iggFWR2g0PIcKsA/SXdRKWPqCHG2uKHBvdRTQGupdXQ1sbV+AHw 30 | ycyA/9H/mp/NUSNM2cqnBDcZ6GhlHt59zWtEveiuU5fpTbp4GVcFXbW8jStj8j8z 31 | 1HI3cywZO8+YNPzqyx0JWsidXGkfzkPHyS4jTG84lfu2JG8m/nqLnRSeKpl20Q== 32 | =79bX 33 | -----END PGP PUBLIC KEY BLOCK----- 34 | -------------------------------------------------------------------------------- /convert2rhel/i18n.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright(C) 2021 Red Hat, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | """ 18 | One location to keep all locale related information. 19 | 20 | convert2rhel is not currently localized but it does interact with other systems which are. this 21 | module provides a single place to keep that information. If we decide to localize convert2rhel in 22 | the future, this file should point us towards all the locations that we may need to change. 23 | """ 24 | 25 | __metaclass__ = type 26 | 27 | # 28 | # Display locales 29 | # 30 | 31 | # These locales are about what we want to display to the user. If we decide to localize, these 32 | # should be updated to retrieve the locale setting (Using the locale module from the python stdlib). 33 | CONVERT2RHEL_LOCALE = "C" 34 | # Subscription-manager's DBus API has its own method to set the locale. I'm not sure whether we 35 | # would want these to obey the Display locale of the programming locale. We're likely to forward 36 | # the error messages on to the user so display locale feels like the best fit but sometimes error 37 | # messages are best left un-localized so that they are easier to perform a web-search for. 38 | # We can make a decision if/when we're ready to localize convert2rhel. 39 | SUBSCRIPTION_MANAGER_LOCALE = CONVERT2RHEL_LOCALE 40 | 41 | # 42 | # Programming Locale 43 | # 44 | 45 | # This is the locale to use for programs that we run in a subprocess and then have to interpret what 46 | # they have done by screenscraping their output. 47 | SCREENSCRAPED_LOCALE = "C" 48 | -------------------------------------------------------------------------------- /convert2rhel/pkgmanager/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/pkgmanager/handlers/base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright(C) 2022 Red Hat, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | __metaclass__ = type 19 | 20 | import abc 21 | 22 | import six 23 | 24 | 25 | @six.add_metaclass(abc.ABCMeta) 26 | class TransactionHandlerBase: 27 | """Abstract class that defines a common interface for the handlers. 28 | 29 | This class is not meant to have actual code implementation, only abstract 30 | methods that will have a "contract" between the other transaction handlers 31 | classes that inherit it in their implementation, thus, overriding the 32 | actual usage of the public methods listed here. 33 | 34 | _base: yum.YumBase | dnf.Base 35 | Instance of the base class, either YumBase() or Base() 36 | _enabled_repos: list[str] 37 | List of repositories to be enabled. 38 | """ 39 | 40 | @abc.abstractmethod 41 | def __init__(self): 42 | self._base = None 43 | self._enabled_repos = [] 44 | 45 | @abc.abstractmethod 46 | def run_transaction(self, validate_transaction=False): 47 | """Run the actual transaction for the base class. 48 | 49 | :param validate_transaction: Determines if the transaction needs to be tested or not. 50 | :type validate_transaction: bool 51 | """ 52 | pass 53 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/conversion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/convert2rhel/unit_tests/actions/conversion/__init__.py -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/conversion/pkg_manager_config_test.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2024 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | import pytest 18 | import six 19 | 20 | from convert2rhel import redhatrelease 21 | from convert2rhel.actions.conversion import pkg_manager_config 22 | 23 | 24 | six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) 25 | from six.moves import mock 26 | 27 | 28 | @pytest.fixture 29 | def pkg_manager_config_instance(): 30 | return pkg_manager_config.ConfigurePkgManager() 31 | 32 | 33 | def test_pkg_manager_config(pkg_manager_config_instance, monkeypatch): 34 | redhat_release_mock = mock.Mock() 35 | monkeypatch.setattr(redhatrelease.PkgManagerConf, "patch", redhat_release_mock) 36 | pkg_manager_config_instance.run() 37 | 38 | assert redhat_release_mock.call_count == 1 39 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/aliased_action_name/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/aliased_action_name/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel.actions import Action as Foo 4 | 5 | 6 | class RealTest(Foo): 7 | id = "REALTEST" 8 | 9 | def run(self): 10 | pass 11 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/extraneous_files/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/extraneous_files/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class RealTest(actions.Action): 7 | id = "REALTEST" 8 | 9 | def run(self): 10 | pass 11 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/extraneous_files/test.txt: -------------------------------------------------------------------------------- 1 | from convert2rhel import actions 2 | 3 | 4 | class Test(actions.Action): 5 | pass 6 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/ignore__init__/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class Test(actions.Action): 7 | id = "TEST" 8 | 9 | def run(self): 10 | pass 11 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/ignore__init__/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class RealTest(actions.Action): 7 | id = "REALTEST" 8 | 9 | def run(self): 10 | pass 11 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/multiple_actions_multiple_files/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/multiple_actions_multiple_files/test1.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class TestAction1(actions.Action): 7 | id = "TestAction1" 8 | 9 | def run(self): 10 | pass 11 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/multiple_actions_multiple_files/test2.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class TestAction2(actions.Action): 7 | id = "TestAction2" 8 | 9 | def run(self): 10 | pass 11 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/multiple_actions_one_file/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/multiple_actions_one_file/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class RealTest(actions.Action): 7 | id = "REALTEST" 8 | 9 | def run(self): 10 | pass 11 | 12 | 13 | class SecondTest(actions.Action): 14 | id = "SECONDTEST" 15 | 16 | def run(self): 17 | pass 18 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/not_action_itself/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/not_action_itself/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | AlternateName = actions.Action 7 | 8 | 9 | class RealTest(AlternateName): 10 | id = "REALTEST" 11 | 12 | def run(self): 13 | pass 14 | 15 | 16 | class OtherTest(actions.Action): 17 | id = "OTHERTEST" 18 | 19 | def run(self): 20 | pass 21 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/only_subclasses_of_action/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/only_subclasses_of_action/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class RealTest(actions.Action): 7 | id = "REALTEST" 8 | 9 | def run(self): 10 | pass 11 | 12 | 13 | class NotAction: 14 | pass 15 | 16 | 17 | class AlsoNotAction(NotAction): 18 | pass 19 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/action_exceptions/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/action_exceptions/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | 4 | from convert2rhel import actions 5 | from convert2rhel.logger import root_logger 6 | 7 | 8 | logger = root_logger.getChild(__name__) 9 | 10 | 11 | class DivideByZeroTest(actions.Action): 12 | id = "DIVIDEBYZEROTEST" 13 | dependencies = ("SUCCESSTEST",) 14 | 15 | def run(self): 16 | super(DivideByZeroTest, self).run() 17 | return 1 / 0 18 | 19 | 20 | class LogCriticalTest(actions.Action): 21 | id = "LOGCRITICALTEST" 22 | dependencies = ("SUCCESSTEST",) 23 | 24 | def run(self): 25 | super(LogCriticalTest, self).run() 26 | logger.critical("Critical log will cause a SystemExit.") 27 | 28 | 29 | class SuccessTest(actions.Action): 30 | id = "SUCCESSTEST" 31 | 32 | def run(self): 33 | super(SuccessTest, self).run() 34 | return 35 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/all_status_actions/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/bad_deps1/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/bad_deps1/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class BadTest1(actions.Action): 7 | id = "BADTEST1" 8 | dependencies = ("BADTEST2",) 9 | 10 | def run(self): 11 | super(BadTest1, self).run() 12 | return 13 | 14 | 15 | class BadTest2(actions.Action): 16 | id = "BADTEST2" 17 | dependencies = ("BADTEST1",) 18 | 19 | def run(self): 20 | super(BadTest2, self).run() 21 | return 22 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/deps_on_1/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/deps_on_1/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class TestI(actions.Action): 7 | id = "TESTI" 8 | dependencies = ("REALTEST",) 9 | 10 | def run(self): 11 | super(TestI, self).run() 12 | return 13 | 14 | 15 | class TestII(actions.Action): 16 | id = "TESTII" 17 | dependencies = ("REALTEST", "FOURTHTEST") 18 | 19 | def run(self): 20 | super(TestII, self).run() 21 | return 22 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/good_deps1/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/good_deps1/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class RealTest(actions.Action): 7 | id = "REALTEST" 8 | 9 | def run(self): 10 | super(RealTest, self).run() 11 | return 12 | 13 | 14 | class SecondTest(actions.Action): 15 | id = "SECONDTEST" 16 | dependencies = ("REALTEST",) 17 | 18 | def run(self): 19 | super(SecondTest, self).run() 20 | return 21 | 22 | 23 | class ThirdTest(actions.Action): 24 | id = "THIRDTEST" 25 | dependencies = ("REALTEST",) 26 | 27 | def run(self): 28 | super(ThirdTest, self).run() 29 | return 30 | 31 | 32 | class FourthTest(actions.Action): 33 | id = "FOURTHTEST" 34 | dependencies = ("SECONDTEST", "THIRDTEST") 35 | 36 | def run(self): 37 | super(FourthTest, self).run() 38 | return 39 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/good_deps_failed_actions/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/data/stage_tests/good_deps_failed_actions/test.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | 3 | from convert2rhel import actions 4 | 5 | 6 | class ATest(actions.Action): 7 | id = "ATEST" 8 | dependencies = ("BTEST",) 9 | 10 | def run(self): 11 | super(ATest, self).run() 12 | return 13 | 14 | 15 | class BTest(actions.Action): 16 | id = "BTEST" 17 | 18 | def run(self): 19 | super(BTest, self).run() 20 | self.set_status( 21 | level=actions.STATUS_CODES["ERROR"], 22 | id="BTEST_FAILURE", 23 | title="failure title", 24 | description="failure description", 25 | diagnosis="failure diagnosis", 26 | remediations="failure remediations", 27 | ) 28 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/post_conversion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/convert2rhel/unit_tests/actions/post_conversion/__init__.py -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/post_conversion/breadcrumbs_finish_collection_test.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2024 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | import pytest 19 | import six 20 | 21 | from convert2rhel.actions.post_conversion import breadcrumbs_finish_collection 22 | 23 | 24 | six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) 25 | from six.moves import mock 26 | 27 | 28 | @pytest.fixture 29 | def breadcrumbs_finish_collection_instance(): 30 | return breadcrumbs_finish_collection.BreadcumbsFinishCollection() 31 | 32 | 33 | def test_breadcrumbs_finish_collection(monkeypatch, caplog, breadcrumbs_finish_collection_instance): 34 | finish_collection = mock.Mock() 35 | monkeypatch.setattr(breadcrumbs_finish_collection.breadcrumbs.breadcrumbs, "finish_collection", finish_collection) 36 | 37 | breadcrumbs_finish_collection_instance.run() 38 | 39 | assert "Update breadcrumbs" in caplog.records[-1].message 40 | assert finish_collection.call_count == 1 41 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/pre_ponr_changes/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/system_checks/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/actions/system_checks/grub_validity_test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright(C) 2024 Red Hat, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | __metaclass__ = type 19 | 20 | 21 | import pytest 22 | 23 | from convert2rhel import unit_tests, utils 24 | from convert2rhel.actions.system_checks import grub_validity 25 | from convert2rhel.unit_tests import RunSubprocessMocked 26 | 27 | 28 | @pytest.fixture 29 | def grub_validity_instance(): 30 | return grub_validity.GrubValidity() 31 | 32 | 33 | def test_grub_validity_error(grub_validity_instance, monkeypatch): 34 | monkeypatch.setattr(utils, "run_subprocess", RunSubprocessMocked(return_value=("output", 127))) 35 | grub_validity_instance.run() 36 | unit_tests.assert_actions_result( 37 | grub_validity_instance, 38 | level="ERROR", 39 | id="INVALID_GRUB_FILE", 40 | title="Grub boot entry file is invalid", 41 | description="The grub file seems to be invalid leaving the system in a" 42 | " non-clean state and must be fixed before continuing the conversion" 43 | " to ensure a smooth process.", 44 | remediations="Check the grub file inside `/etc/default` directory and remove any " 45 | "misconfigurations, then re-run the conversion.", 46 | ) 47 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/backup/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/convert2rhel/unit_tests/backup/__init__.py -------------------------------------------------------------------------------- /convert2rhel/unit_tests/dummy_file: -------------------------------------------------------------------------------- 1 | Dummy file to read by built-in open function that cannot be mocked. 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/initialize_test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright(C) 2022 Red Hat, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | __metaclass__ = type 19 | 20 | import pytest 21 | import six 22 | 23 | from convert2rhel import applock, initialize 24 | from convert2rhel import logger as logger_module 25 | from convert2rhel import main 26 | 27 | 28 | six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) 29 | from six.moves import mock 30 | 31 | 32 | @pytest.mark.parametrize( 33 | ("exit_code"), 34 | ( 35 | (0), 36 | (1), 37 | ), 38 | ) 39 | def test_run(monkeypatch, exit_code, tmp_path): 40 | monkeypatch.setattr(logger_module, "LOG_DIR", str(tmp_path)) 41 | monkeypatch.setattr(main, "main", value=lambda: exit_code) 42 | monkeypatch.setattr(applock, "_DEFAULT_LOCK_DIR", str(tmp_path)) 43 | assert initialize.run() == exit_code 44 | 45 | 46 | def test_initialize_logger(monkeypatch): 47 | setup_logger_handler_mock = mock.Mock() 48 | 49 | monkeypatch.setattr( 50 | logger_module, 51 | "setup_logger_handler", 52 | value=setup_logger_handler_mock, 53 | ) 54 | 55 | initialize.initialize_logger() 56 | setup_logger_handler_mock.assert_called_once() 57 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/other_test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright(C) 2016 Red Hat, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | __metaclass__ = type 19 | 20 | import re 21 | 22 | from convert2rhel import __version__, logger, pkghandler, utils 23 | 24 | 25 | RPM_SPEC_VERSION_RE = re.compile(r"^Version: +(.+)$") 26 | 27 | 28 | def test_correct_constants(): 29 | # Prevents unintentional change of constants 30 | assert utils.TMP_DIR == "/var/lib/convert2rhel/" 31 | assert utils.DATA_DIR == "/usr/share/convert2rhel/" 32 | assert pkghandler.MAX_YUM_CMD_CALLS == 3 33 | assert logger.LOG_DIR == "/var/log/convert2rhel" 34 | 35 | 36 | def test_package_version(pkg_root): 37 | # version should be a string 38 | assert isinstance(__version__, str) 39 | # version should be separated with dots, i.e. "1.1.1b" 40 | assert len(__version__.split(".")) > 1 41 | # versions specified in rpm spec and convert2rhel.__init__ should match 42 | with open(str(pkg_root / "packaging/convert2rhel.spec")) as spec_f: 43 | for line in spec_f: 44 | if RPM_SPEC_VERSION_RE.match(line): 45 | assert __version__ == RPM_SPEC_VERSION_RE.findall(line)[0] 46 | break 47 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/pkgmanager/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/pkgmanager/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/pkgmanager/handlers/dnf/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/pkgmanager/handlers/yum/__init__.py: -------------------------------------------------------------------------------- 1 | __metaclass__ = type 2 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.ruff] 2 | # Extend the `pyproject.toml` file in the parent directory... 3 | extend = "../../pyproject.toml" 4 | 5 | [tool.ruff.lint] 6 | ignore = ["E402"] 7 | -------------------------------------------------------------------------------- /convert2rhel/unit_tests/toolopts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/convert2rhel/unit_tests/toolopts/__init__.py -------------------------------------------------------------------------------- /convert2rhel/unit_tests/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/convert2rhel/unit_tests/utils/__init__.py -------------------------------------------------------------------------------- /convert2rhel/utils/files.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright(C) 2024 Red Hat, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | __metaclass__ = type 19 | 20 | 21 | import errno 22 | import os 23 | 24 | 25 | def mkdir_p(path): 26 | """Create all missing directories for the path. 27 | 28 | :param str path: Absolute path to create directories for 29 | :raises OSError: If it fails to create directories. Does not raise if the path already exists. 30 | """ 31 | try: 32 | os.makedirs(path) 33 | except OSError as err: 34 | if err.errno == errno.EEXIST and os.path.isdir(path): 35 | return 36 | raise 37 | -------------------------------------------------------------------------------- /convert2rhel/utils/rpm.py: -------------------------------------------------------------------------------- 1 | # Copyright(C) 2024 Red Hat, Inc. 2 | # 3 | # This program is free software: you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation, either version 3 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program. If not, see . 15 | 16 | __metaclass__ = type 17 | 18 | # For a list of modified rpm files before the conversion starts 19 | PRE_RPM_VA_LOG_FILENAME = "rpm_va.log" 20 | 21 | # For a list of modified rpm files after the conversion finishes for comparison purposes 22 | POST_RPM_VA_LOG_FILENAME = "rpm_va_after_conversion.log" 23 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | PYTHON = python3 12 | 13 | # Put it first so that "make" without argument is like "make help". 14 | help: 15 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 16 | 17 | serve: 18 | @$(PYTHON) -m http.server --directory build/html 19 | 20 | .PHONY: help Makefile serve 21 | 22 | # Catch-all target: route all unknown targets to Sphinx using the new 23 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 24 | %: Makefile 25 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 26 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx==7.4.7 # need to use this version as Sphinx 8+ requires py3.11+ and CentOS Stream 9 we use for building docs has py3.9 2 | sphinx_autodoc_typehints==2.3.0 # can't use newer due to the Sphinx 7.4.7 requirement 3 | -------------------------------------------------------------------------------- /docs/source/_static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/docs/source/_static/.gitkeep -------------------------------------------------------------------------------- /docs/source/_templates/custom-class-template.rst: -------------------------------------------------------------------------------- 1 | {{ fullname | escape | underline}} 2 | 3 | .. currentmodule:: {{ module }} 4 | 5 | .. autoclass:: {{ objname }} 6 | :members: 7 | :show-inheritance: 8 | :inherited-members: 9 | :special-members: __call__, __add__, __mul__ 10 | 11 | {% block methods %} 12 | {% if methods %} 13 | .. rubric:: {{ _('Methods') }} 14 | 15 | .. autosummary:: 16 | :nosignatures: 17 | {% for item in methods %} 18 | {%- if not item.startswith('_') %} 19 | ~{{ name }}.{{ item }} 20 | {%- endif -%} 21 | {%- endfor %} 22 | {% endif %} 23 | {% endblock %} 24 | 25 | {% block attributes %} 26 | {% if attributes %} 27 | .. rubric:: {{ _('Attributes') }} 28 | 29 | .. autosummary:: 30 | {% for item in attributes %} 31 | ~{{ name }}.{{ item }} 32 | {%- endfor %} 33 | {% endif %} 34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /docs/source/_templates/custom-module-template.rst: -------------------------------------------------------------------------------- 1 | {{ fullname | escape | underline}} 2 | 3 | .. automodule:: {{ fullname }} 4 | 5 | {% block attributes %} 6 | {% if attributes %} 7 | .. rubric:: Module attributes 8 | 9 | .. autosummary:: 10 | :toctree: 11 | {% for item in attributes %} 12 | {{ item }} 13 | {%- endfor %} 14 | {% endif %} 15 | {% endblock %} 16 | 17 | {% block functions %} 18 | {% if functions %} 19 | .. rubric:: {{ _('Functions') }} 20 | 21 | .. autosummary:: 22 | :toctree: 23 | :nosignatures: 24 | {% for item in functions %} 25 | {{ item }} 26 | {%- endfor %} 27 | {% endif %} 28 | {% endblock %} 29 | 30 | {% block classes %} 31 | {% if classes %} 32 | .. rubric:: {{ _('Classes') }} 33 | 34 | .. autosummary:: 35 | :toctree: 36 | :template: custom-class-template.rst 37 | :nosignatures: 38 | {% for item in classes %} 39 | {{ item }} 40 | {%- endfor %} 41 | {% endif %} 42 | {% endblock %} 43 | 44 | {% block exceptions %} 45 | {% if exceptions %} 46 | .. rubric:: {{ _('Exceptions') }} 47 | 48 | .. autosummary:: 49 | :toctree: 50 | {% for item in exceptions %} 51 | {{ item }} 52 | {%- endfor %} 53 | {% endif %} 54 | {% endblock %} 55 | 56 | {% block modules %} 57 | {% if modules %} 58 | 59 | .. rubric:: {{ _('Submodules') }} 60 | 61 | .. autosummary:: 62 | :toctree: 63 | :template: custom-module-template.rst 64 | :recursive: 65 | {% for item in modules %} 66 | {{ item }} 67 | {%- endfor %} 68 | {% endif %} 69 | {% endblock %} 70 | -------------------------------------------------------------------------------- /docs/source/actions.rst: -------------------------------------------------------------------------------- 1 | Actions 2 | ####### 3 | 4 | Generic documentation TBA 5 | 6 | Actions API Docs 7 | ---------------- 8 | 9 | .. autosummary:: 10 | :toctree: _autosummary 11 | :template: custom-module-template.rst 12 | :recursive: 13 | 14 | convert2rhel.actions 15 | -------------------------------------------------------------------------------- /docs/source/all.rst: -------------------------------------------------------------------------------- 1 | Complete API Docs 2 | ================= 3 | 4 | .. autosummary:: 5 | :toctree: _autosummary 6 | :template: custom-module-template.rst 7 | :recursive: 8 | 9 | convert2rhel 10 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to convert2rhel Development Documentation 2 | ================================================= 3 | 4 | .. toctree:: 5 | :maxdepth: 3 6 | :caption: Contents: 7 | 8 | all 9 | meta 10 | actions 11 | 12 | Indices and tables 13 | ================== 14 | 15 | * :ref:`genindex` 16 | * :ref:`modindex` 17 | * :ref:`search` 18 | -------------------------------------------------------------------------------- /docs/source/pkgmanager.rst: -------------------------------------------------------------------------------- 1 | Package Manager 2 | ############### 3 | 4 | Generic documentation TBA 5 | 6 | Package Manager API Docs 7 | ------------------------ 8 | 9 | .. automodule:: convert2rhel.pkgmanager 10 | :members: 11 | -------------------------------------------------------------------------------- /man/distribution.man: -------------------------------------------------------------------------------- 1 | [DISTRIBUTION] 2 | https://cdn.redhat.com/content/public/convert2rhel/ 3 | -------------------------------------------------------------------------------- /man/synopsis: -------------------------------------------------------------------------------- 1 | [synopsis] 2 | . 3 | convert2rhel [--version] [-h] 4 | convert2rhel [-u username] [-p password | -c conf_file_path] [--pool pool_id | -a] [--disablerepo repoid] [--enablerepo repoid] [--serverurl url] [--no-rpm-va] [--els] [--eus] [--debug] [--restart] [-y] 5 | convert2rhel [--no-rhsm] [--disablerepo repoid] [--enablerepo repoid] [--no-rpm-va] [--els ] [--eus] [--debug] [--restart] [-y] 6 | convert2rhel [-k activation_key | -c conf_file_path] [-o organization] [--pool pool_id | -a] [--disablerepo repoid] [--enablerepo repoid] [--serverurl url] [--no-rpm-va] [--els] [--eus] [--debug] [--restart] [-y] 7 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.vulture] 2 | exclude = ["convert2rhel/unit_tests/actions/data"] 3 | ignore_decorators = ["@pytest.fixture"] 4 | ignore_names = ["pretend_os", "stage_actions"] 5 | min_confidence = 90 6 | paths = ["convert2rhel", "scripts/whitelist.py"] 7 | 8 | [tool.ruff] 9 | builtins = ["convert2rhel", "six"] 10 | 11 | 12 | line-length = 120 13 | fix = true 14 | 15 | # We technically only support py27 py36 due to el7 and el8 but ruff only 16 | # supports py37 as minimum. This is not a huge issue as any rules we do not 17 | # want we can disable 18 | target-version = "py37" 19 | 20 | [tool.ruff.lint] 21 | # Set our root_logger as the de-facto logger 22 | logger-objects = ["convert2rhel.logger.root_logger"] 23 | extend-select = [ 24 | "UP031", # Forbid percent-string formatting 25 | ] 26 | 27 | [tool.ruff.lint.per-file-ignores] 28 | "whitelist.py" = [ 29 | "F821", # For ignoring undefined variables in this file 30 | ] 31 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = --setup-show -svv 3 | testpaths = "convert2rhel/unit_tests" 4 | # Ignore out any len() deprecation that is inside yum, we can't fix that and 5 | # is only relevant for el7 conversions, which is the only one who needs py27 anyway 6 | filterwarnings = 7 | ignore:.*use len\(mi\) instead.*:PendingDeprecationWarning 8 | markers = 9 | cert_filename 10 | rhsm_returns 11 | popen_output 12 | # Integration test related markers 13 | reboot_after_conversion 14 | prepare_isolated_system 15 | # Unit test related 16 | noautofixtures: disable all auto-use fixtures 17 | -------------------------------------------------------------------------------- /requirements/centos7.requirements.txt: -------------------------------------------------------------------------------- 1 | pytest==4.6.11 2 | pathlib2==2.3.7.post1 3 | mock==3.0.5 4 | pytest-cov==2.12.1 5 | pytest-xdist==1.34.0 6 | -------------------------------------------------------------------------------- /requirements/centos8.requirements.txt: -------------------------------------------------------------------------------- 1 | pytest==7.0.1 2 | pytest-cov==3.0.0 3 | coverage[toml] 4 | pytest-xdist==1.34.0 5 | -------------------------------------------------------------------------------- /requirements/centos9.requirements.txt: -------------------------------------------------------------------------------- 1 | pytest==7.0.1 2 | pytest-cov==3.0.0 3 | coverage[toml] 4 | pytest-xdist==1.34.0 5 | -------------------------------------------------------------------------------- /scripts/build_locally.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # Run this script on CentOS Linux/OL/RHEL 7/8/9 6 | echo "Creating a tarball for building the RPM ..." 7 | if [ -x "$(command -v python3)" ]; then 8 | python3 setup.py sdist 9 | elif [ -x "$(command -v python2)" ]; then 10 | python2 setup.py sdist 11 | else 12 | echo "Error: Can't find python interpreter." 13 | exit 1 14 | fi 15 | echo "Setting up RPM tree in \$HOME" 16 | rpmdev-setuptree 17 | cp -v dist/* ~/rpmbuild/SOURCES 18 | echo "Building the RPM ..." 19 | if [ $container == "podman" ]; then 20 | echo "Detected running in podman, will not clean up" 21 | rpmbuild -ba packaging/convert2rhel.spec --define "debug_package %{nil}" 22 | else 23 | echo "Detected running locally, cleaning up afterwards" 24 | rpmbuild -ba packaging/convert2rhel.spec --define "debug_package %{nil}" --clean 25 | fi 26 | echo "RPM was built successfully" 27 | echo "Cleaning up the target directory..." 28 | mkdir -p .rpms 29 | mkdir -p .srpms 30 | mv -vf ~/rpmbuild/RPMS/noarch/convert2rhel* .rpms/ 31 | mv -vf ~/rpmbuild/SRPMS/convert2rhel* .srpms/ 32 | echo "RPM was moved to the target directory." 33 | -------------------------------------------------------------------------------- /scripts/extract_version_from_rpm_spec.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import click 4 | 5 | 6 | @click.command() 7 | @click.argument("spec_path") 8 | def get_convert2rhel_version(spec_path: str) -> None: 9 | """Parse rpm spec file and returns its name-version-release part. 10 | 11 | Example: 12 | ```bash 13 | python scripts/extract_version_from_rpm_spec.py packaging/convert2rhel.spec 14 | # 0.21-1 15 | ``` 16 | 17 | """ 18 | with open(spec_path) as rpm_f: 19 | try: 20 | click.echo( 21 | "-".join( 22 | re.findall( 23 | r""" 24 | # Line which starts with these words 25 | ^(?:Version|Release): 26 | # Spaces afterwards 27 | \s+ 28 | # capturing group which we are interested in 29 | ( 30 | # Any word could be here 31 | (?:\w+)| 32 | # Or int or float i.e. 21 or 0.21 or 1.5.0 33 | (?:\d+[.]*\d*[.]*\d*) 34 | ) 35 | # some special internal rpm spec var (skipping it) 36 | (?:%{.+)*$ 37 | """, 38 | rpm_f.read(), 39 | flags=(re.MULTILINE | re.VERBOSE), 40 | ) 41 | ), 42 | ) 43 | except Exception as e: 44 | raise click.ClickException(repr(e)) from e 45 | 46 | 47 | __name__ == "__main__" and get_convert2rhel_version() 48 | -------------------------------------------------------------------------------- /scripts/manpage_generation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Directory to store the generated manpages 4 | MANPAGE_DIR="man" 5 | 6 | echo Generating manpages 7 | 8 | VER=$(grep -oP '^Version:\s+\K\S+' packaging/convert2rhel.spec) 9 | 10 | echo Generating for version $VER 11 | # Generate a file with convert2rhel synopsis for argparse-manpage 12 | /usr/bin/python -c 'from convert2rhel import toolopts; print("[synopsis]\n."+toolopts.CLI.usage())' > man/synopsis 13 | 14 | /usr/bin/python -m pip install argparse-manpage six pexpect 15 | 16 | # Generate the manpage using argparse-manpage 17 | PYTHONPATH=. /usr/bin/python /home/runner/.local/bin/argparse-manpage --pyfile man/__init__.py --function get_parser --manual-title="General Commands Manual" --description="Automates the conversion of Red Hat Enterprise Linux derivative distributions to Red Hat Enterprise Linux." --project-name "convert2rhel $VER" --prog="convert2rhel" --include man/distribution --include man/synopsis > "$MANPAGE_DIR/convert2rhel.8" 18 | 19 | git status 20 | -------------------------------------------------------------------------------- /scripts/whitelist.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file is intended to hold a list of variables (and their respective paths) 3 | of things to be ignored by vulture. 4 | """ 5 | 6 | ti_done # unused variable (convert2rhel/pkgmanager/handlers/dnf/callback.py:231) 7 | ti_total # unused variable (convert2rhel/pkgmanager/handlers/dnf/callback.py:231) 8 | te_current # unused variable (convert2rhel/pkgmanager/handlers/yum/callback.py:126) 9 | te_total # unused variable (convert2rhel/pkgmanager/handlers/yum/callback.py:126) 10 | kwds # unused variable (convert2rhel/unit_tests/pkgmanager/handlers/dnf/dnf_test.py:56) 11 | z # unused variable (convert2rhel/unit_tests/utils_test.py:470) 12 | cols # unused variable (convert2rhel/utils.py:491) 13 | rows # unused variable (convert2rhel/utils.py:491) 14 | x # unused variable (convert2rhel/unit_tests/actions/pre_ponr_changes/subscription_test.py:68) 15 | y # unused variable (convert2rhel/unit_tests/utils/utils_test.py:473) 16 | -------------------------------------------------------------------------------- /tests/ansible_collections/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | build_rpm: "{{ lookup('env', 'ANSIBLE_BUILD_RPM') }}" 3 | rpm_provider: "{{ lookup('env', 'ANSIBLE_RPM_PROVIDER') }}" 4 | rpm_url_el7: "{{ lookup('env', 'ANSIBLE_RPM_URL_EL7') }}" 5 | rpm_url_el8: "{{ lookup('env', 'ANSIBLE_RPM_URL_EL8') }}" 6 | rhsm_password: "{{ lookup('env', 'RHSM_SCA_PASSWORD') }}" 7 | rhsm_username: "{{ lookup('env', 'RHSM_SCA_USERNAME') }}" 8 | rhsm_server_url: "{{ lookup('env', 'RHSM_SERVER_URL') }}" 9 | -------------------------------------------------------------------------------- /tests/ansible_collections/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | roles: 4 | 5 | - role: hardcode-eus-version-repos 6 | when: > 7 | ansible_facts['distribution_version'] == "8.8" 8 | and ansible_facts['distribution'] in ["AlmaLinux", "Rocky"] 9 | 10 | - role: remove-tf-artifact-leftovers 11 | 12 | - role: update-system 13 | when: lookup('env', 'TESTS_DONT_UPDATE_SYSTEM') != "1" 14 | 15 | - role: grub-setup 16 | when: ansible_facts['distribution_major_version'] == "9" 17 | 18 | - role: oracle-linux-specific 19 | when: ansible_facts['distribution'] == "OracleLinux" 20 | 21 | - role: packaging 22 | 23 | - role: install-testing-deps 24 | 25 | - role: get-test-vars 26 | 27 | - role: update-ca-trust 28 | 29 | - import_playbook: roles/reboot/main.yml 30 | when: lookup('env', 'TESTS_DONT_UPDATE_SYSTEM') != "1" 31 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/add-custom-repos/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | gather_facts: yes 4 | become: false 5 | - import_playbook: rhel7-repos.yml 6 | when: ansible_facts['distribution_major_version'] == "7" 7 | #TODO(danmyway) bump when new minor available 8 | - import_playbook: rhel8-repos.yml 9 | when: ansible_facts['distribution_major_version'] == "8" 10 | - import_playbook: rhel8-eus-repos.yml 11 | # We need to skip for Oracle Linux machines since we don't test EUS on OL 12 | when: ansible_facts['distribution_version'] == "8.8" and ansible_facts['distribution'] != "OracleLinux" 13 | - import_playbook: rhel9-repos.yml 14 | when: ansible_facts['distribution_major_version'] == "9" 15 | - import_playbook: rhel9-eus-repos.yml 16 | # We need to skip for Oracle Linux machines since we don't test EUS on OL 17 | when: ansible_facts['distribution_version'] in ["9.2", "9.4", "9.6", "9.8"] and ansible_facts['distribution'] != "OracleLinux" 18 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/add-custom-repos/rhel7-repos.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Add rhel7 server rpms repo 4 | yum_repository: 5 | name: rhel-7-server-rpms 6 | description: RHEL 7.9 for $basearch 7 | baseurl: https://rhsm-pulp.corp.redhat.com/content/dist/rhel/server/7/$releasever/$basearch/os/ 8 | gpgcheck: no 9 | enabled: no 10 | file: rhel7 11 | 12 | - name: Add rhel7 server optional rpms 13 | yum_repository: 14 | name: rhel-7-server-optional-rpms 15 | description: RHEL 7.9 Optional for $basearch 16 | baseurl: https://rhsm-pulp.corp.redhat.com/content/dist/rhel/server/7/$releasever/$basearch/optional/os/ 17 | gpgcheck: no 18 | enabled: no 19 | file: rhel7 20 | 21 | - name: Add rhel7 server extras rpms 22 | yum_repository: 23 | name: rhel-7-server-extras-rpms 24 | description: RHEL 7 Extras for $basearch 25 | baseurl: https://rhsm-pulp.corp.redhat.com/content/dist/rhel/server/7/$releasever/$basearch/extras/os/ 26 | gpgcheck: no 27 | enabled: no 28 | file: rhel7 29 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/add-custom-repos/rhel8-eus-repos.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Add rhel8 baseos eus repo 4 | yum_repository: 5 | name: rhel-8-for-x86_64-baseos-eus-rpms 6 | description: RHEL 8 BaseOS for $basearch 7 | baseurl: https://rhsm-pulp.corp.redhat.com/content/eus/rhel8/$releasever/$basearch/baseos/os/ 8 | gpgcheck: no 9 | enabled: no 10 | file: rhel8-eus 11 | 12 | - name: Add rhel8 appstream eus repo 13 | yum_repository: 14 | name: rhel-8-for-x86_64-appstream-eus-rpms 15 | description: RHEL 8 AppStream for $basearch 16 | baseurl: https://rhsm-pulp.corp.redhat.com/content/eus/rhel8/$releasever/$basearch/appstream/os/ 17 | gpgcheck: no 18 | enabled: no 19 | file: rhel8-eus 20 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/add-custom-repos/rhel8-repos.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Add rhel8 baseos repo 4 | yum_repository: 5 | name: rhel-8-for-x86_64-baseos-rpms 6 | description: RHEL 8 BaseOS for $basearch 7 | baseurl: https://rhsm-pulp.corp.redhat.com/content/dist/rhel8/$releasever/$basearch/baseos/os/ 8 | gpgcheck: no 9 | enabled: no 10 | file: rhel8 11 | 12 | - name: Add rhel8 appstream repo 13 | yum_repository: 14 | name: rhel-8-for-x86_64-appstream-rpms 15 | description: RHEL 8 AppStream for $basearch 16 | baseurl: https://rhsm-pulp.corp.redhat.com/content/dist/rhel8/$releasever/$basearch/appstream/os/ 17 | gpgcheck: no 18 | enabled: no 19 | file: rhel8 20 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/add-custom-repos/rhel9-eus-repos.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Add rhel9 baseos eus repo 4 | yum_repository: 5 | name: rhel-9-for-x86_64-baseos-eus-rpms 6 | description: RHEL 9 BaseOS for $basearch 7 | baseurl: https://rhsm-pulp.corp.redhat.com/content/eus/rhel9/$releasever/$basearch/baseos/os/ 8 | gpgcheck: no 9 | enabled: no 10 | file: rhel9-eus 11 | 12 | - name: Add rhel9 appstream eus repo 13 | yum_repository: 14 | name: rhel-9-for-x86_64-appstream-eus-rpms 15 | description: RHEL 9 AppStream for $basearch 16 | baseurl: https://rhsm-pulp.corp.redhat.com/content/eus/rhel9/$releasever/$basearch/appstream/os/ 17 | gpgcheck: no 18 | enabled: no 19 | file: rhel9-eus 20 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/add-custom-repos/rhel9-repos.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Add rhel9 baseos repo 4 | yum_repository: 5 | name: rhel-9-for-x86_64-baseos-rpms 6 | description: RHEL 9 BaseOS for $basearch 7 | baseurl: https://rhsm-pulp.corp.redhat.com/content/dist/rhel9/$releasever/$basearch/baseos/os/ 8 | gpgcheck: no 9 | enabled: no 10 | file: rhel9 11 | 12 | - name: Add rhel9 appstream repo 13 | yum_repository: 14 | name: rhel-9-for-x86_64-appstream-rpms 15 | description: RHEL 9 AppStream for $basearch 16 | baseurl: https://rhsm-pulp.corp.redhat.com/content/dist/rhel9/$releasever/$basearch/appstream/os/ 17 | gpgcheck: no 18 | enabled: no 19 | file: rhel9 20 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/get-test-vars/tasks/get-test-vars.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Download the test vars file 3 | get_url: 4 | url: https://gitlab.cee.redhat.com/oamg/convert2rhel/convert2rhel-secrets/-/raw/main/.env 5 | validate_certs: false 6 | dest: /var/tmp/.env 7 | mode: '0444' 8 | 9 | - name: Download the Satellite file 10 | get_url: 11 | url: https://gitlab.cee.redhat.com/oamg/convert2rhel/convert2rhel-secrets/-/raw/main/.env_sat_reg2 12 | validate_certs: false 13 | dest: /var/tmp/.env_sat_reg 14 | mode: '0444' 15 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/get-test-vars/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: get-test-vars.yml 3 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/grub-setup/tasks/grub_setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Gather facts 3 | ansible.builtin.setup: 4 | 5 | # Booting an older kernel causes issues due to disabled GRUB_ENABLE_BLSCFG option 6 | # Set the option to true 7 | - name: Set the /etc/grub/default GRUB_ENABLE_BLSCFG 8 | lineinfile: 9 | path: /etc/default/grub 10 | line: 'GRUB_ENABLE_BLSCFG=true' 11 | insertafter: EOF 12 | 13 | # Additionally OracleLinux 9 has the GRUB_TERMINAL_OUTPUT set up weirdly 14 | - name: Set the /etc/grub/default GRUB_TERMINAL_OUTPUT 15 | lineinfile: 16 | path: /etc/default/grub 17 | line: 'GRUB_TERMINAL_OUTPUT="console"' 18 | insertafter: EOF 19 | when: ansible_distribution == "OracleLinux" 20 | 21 | - name: Run grub2-mkconfig 22 | shell: grub2-mkconfig -o /boot/grub2/grub.cfg 23 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/grub-setup/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: grub_setup.yml 3 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/hardcode-eus-version-repos/tasks/alma-eus-repos.yml: -------------------------------------------------------------------------------- 1 | - name: Gather facts 2 | ansible.builtin.setup: 3 | 4 | - name: Overwrite AppStream repository (AlmaLinux {{ ansible_distribution_version }}) 5 | yum_repository: 6 | name: appstream 7 | description: AppStream repo 8 | baseurl: https://repo.almalinux.org/vault/{{ ansible_distribution_version }}/AppStream/$basearch/os/ 9 | state: present 10 | gpgcheck: yes 11 | enabled: yes 12 | gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux 13 | file: almalinux 14 | 15 | - name: Overwrite BaseOS repository (AlmaLinux {{ ansible_distribution_version }}) 16 | yum_repository: 17 | name: baseos 18 | description: BaseOS repo 19 | baseurl: https://repo.almalinux.org/vault/{{ ansible_distribution_version }}/BaseOS/$basearch/os/ 20 | state: present 21 | gpgcheck: yes 22 | enabled: yes 23 | gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux 24 | file: almalinux 25 | 26 | - name: Overwrite Extras repository (AlmaLinux {{ ansible_distribution_version }}) 27 | yum_repository: 28 | name: extras 29 | description: Extras repo 30 | baseurl: https://repo.almalinux.org/vault/{{ ansible_distribution_version }}/extras/$basearch/os/ 31 | state: present 32 | gpgcheck: yes 33 | enabled: yes 34 | gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux 35 | file: almalinux 36 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/hardcode-eus-version-repos/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Hardcode Alma Linux EUS repositories to the vault 3 | include_tasks: alma-eus-repos.yml 4 | when: > 5 | ansible_facts['distribution'] == "AlmaLinux" 6 | and ansible_facts['distribution_version'] in ["8.8", "9.2", "9.4", "9.6", "9.8"] 7 | 8 | - name: Hardcode RockyLinux EUS repositories to the vault 9 | include_tasks: rocky-eus-repos.yml 10 | when: > 11 | ansible_facts['distribution'] == "Rocky" 12 | and ansible_facts['distribution_version'] in ["8.8", "9.2", "9.4", "9.6", "9.8"] 13 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/hardcode-eus-version-repos/tasks/rocky-eus-repos.yml: -------------------------------------------------------------------------------- 1 | - name: Gather facts 2 | ansible.builtin.setup: 3 | 4 | - name: Overwrite AppStream repository (Rocky Linux {{ ansible_distribution_version }}) 5 | yum_repository: 6 | name: appstream 7 | description: AppStream repo 8 | baseurl: https://dl.rockylinux.org/vault/rocky/{{ ansible_distribution_version }}/AppStream/$basearch/os/ 9 | state: present 10 | gpgcheck: yes 11 | enabled: yes 12 | gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial 13 | file: Rocky-AppStream 14 | 15 | - name: Overwrite BaseOS repository (Rocky Linux {{ ansible_distribution_version }}) 16 | yum_repository: 17 | name: baseos 18 | description: BaseOS repo 19 | baseurl: https://dl.rockylinux.org/vault/rocky/{{ ansible_distribution_version }}/BaseOS/$basearch/os/ 20 | state: present 21 | gpgcheck: yes 22 | enabled: yes 23 | gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial 24 | file: Rocky-BaseOS 25 | 26 | - name: Overwrite Extras repository (Rocky Linux {{ ansible_distribution_version }}) 27 | yum_repository: 28 | name: extras 29 | description: Extras repo 30 | baseurl: https://dl.rockylinux.org/vault/rocky/{{ ansible_distribution_version }}/extras/$basearch/os/ 31 | state: present 32 | gpgcheck: yes 33 | enabled: yes 34 | gpgkey: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial 35 | file: Rocky-Extras 36 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/install-testing-deps/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure python3 3 | yum: 4 | # gcc and python3-devel are needed for psutil 5 | name: 6 | - python3 7 | - gcc 8 | - python3-devel 9 | state: present 10 | 11 | - name: Install pip if not present 12 | # ensurepip is available in python-3.4+ 13 | # ensurepip won't install pip if it is already installed 14 | command: python3 -m ensurepip --default-pip 15 | 16 | - name: Update pip 17 | # Possible workaround to fix failing installation of the test dependencies 18 | command: python3 -m pip install --upgrade pip 19 | 20 | - name: Install pytest framework dependencies 21 | pip: 22 | name: 23 | - "pytest" 24 | - "pytest-cov" 25 | - "python-dotenv" 26 | - "click" 27 | - "pexpect" 28 | - "dataclasses" 29 | - "jsonschema" 30 | - "psutil" 31 | # Use pip3 in case pip was installed via rpm package on this system 32 | executable: pip3 33 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/oracle-linux-specific/tasks/boot_standard_kernel.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Gather facts 3 | ansible.builtin.setup: 4 | 5 | - name: Install standard kernel 6 | yum: 7 | name: "kernel.*" 8 | state: latest 9 | 10 | - name: Get installed kernel version 11 | shell: rpm -q --last kernel | head -1 | cut -d " " -f1 | sed 's/kernel-//' 12 | register: kernel_ver 13 | 14 | - name: Set default kernel to Red Hat compatible kernel 15 | shell: "grubby --set-default /boot/vmlinuz-{{ kernel_ver.stdout }}" 16 | 17 | - name: Run grub2-mkconfig 18 | shell: grub2-mkconfig -o /boot/grub2/grub.cfg 19 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/oracle-linux-specific/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: boot_standard_kernel.yml 3 | # We don't want to end up with the latest kernel package from the system repositories in some cases 4 | # e.g. isolated_system_conversion test needs to have the system updated from the Satellite 5 | when: lookup('env', 'TESTS_DONT_UPDATE_SYSTEM') != "1" 6 | # Workaround reference: https://issues.redhat.com/browse/RHELC-1180 7 | - include_tasks: stop_firewalld_workaround.yml 8 | when: ansible_facts['distribution_major_version'] == "8" 9 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/oracle-linux-specific/tasks/stop_firewalld_workaround.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check that the firewalld package is installed 3 | shell: 'rpm -q firewalld' 4 | ignore_errors: True 5 | register: rpm_out 6 | 7 | - name: Replace the firewalld configuration option 8 | ansible.builtin.replace: 9 | path: /etc/firewalld/firewalld.conf 10 | regexp: 'CleanupModulesOnExit=yes' 11 | replace: 'CleanupModulesOnExit=no' 12 | when: rpm_out.rc == 0 13 | 14 | - name: Restart the firewalld process 15 | ansible.builtin.service: 16 | name: firewalld 17 | state: restarted 18 | enabled: true 19 | when: rpm_out.rc == 0 20 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/packaging/tasks/build_rpm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Building rpms 3 | delegate_to: localhost 4 | shell: make rpms 5 | no_log: True 6 | args: 7 | chdir: ../.. 8 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/packaging/tasks/install_rpm_from_local_build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get convert2rhel version 3 | delegate_to: localhost 4 | shell: python scripts/extract_version_from_rpm_spec.py packaging/convert2rhel.spec 5 | args: 6 | chdir: ../.. 7 | register: pkg_version 8 | 9 | - name: Copying rpms to docker remote 10 | delegate_to: localhost 11 | shell: "docker cp .rpms {{ inventory_hostname }}:/data/" 12 | args: 13 | chdir: ../.. 14 | when: ansible_facts['virtualization_type'] == "docker" 15 | 16 | - name: Copying rpms to remote 17 | copy: 18 | dest: ".rpms" 19 | src: ../../.rpms/ 20 | when: ansible_facts['virtualization_type'] != "docker" 21 | 22 | - name: Install el8 convert2rhel package 23 | yum: 24 | name: ".rpms/convert2rhel-{{ pkg_version.stdout }}.el8.noarch.rpm" 25 | state: present 26 | disable_gpg_check: true 27 | when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "8") or 28 | (ansible_facts['distribution'] == "OracleLinux" and ansible_facts['distribution_major_version'] == "8") 29 | 30 | - name: Install el7 convert2rhel package 31 | yum: 32 | name: ".rpms/convert2rhel-{{ pkg_version.stdout }}.el7.noarch.rpm" 33 | state: present 34 | disable_gpg_check: true 35 | when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "7") or 36 | (ansible_facts['distribution'] == "OracleLinux" and ansible_facts['distribution_major_version'] == "7") 37 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/packaging/tasks/install_rpm_from_url.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install el8 convert2rhel package from url 3 | yum: 4 | name: "{{ rpm_url_el8 }}" 5 | state: present 6 | disable_gpg_check: true 7 | when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "8") or 8 | (ansible_facts['distribution'] == "OracleLinux" and ansible_facts['distribution_major_version'] == "8") 9 | 10 | - name: Install el7 convert2rhel package from url 11 | yum: 12 | name: "{{ rpm_url_el7 }}" 13 | state: present 14 | disable_gpg_check: true 15 | when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "7") or 16 | (ansible_facts['distribution'] == "OracleLinux" and ansible_facts['distribution_major_version'] == "7") 17 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/packaging/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: build_rpm.yml 3 | when: build_rpm == "build" 4 | - include_tasks: install_rpm_from_local_build.yml 5 | when: (rpm_provider == "local") and 6 | (build_rpm == "build") 7 | - include_tasks: install_rpm_from_url.yml 8 | when: (rpm_provider == "url") 9 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/reboot/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | tasks: 4 | - name: Reboot the system 5 | reboot: 6 | reboot_timeout: 900 7 | register: back_again 8 | ignore_errors: yes 9 | 10 | - name: Wait additional 10 minutes and try to reconnect (in case of previous task timeout/connection issue) 11 | wait_for_connection: 12 | timeout: 600 13 | # when reboot is successful "changed" is true 14 | register: back_again2 15 | when: not back_again.changed 16 | ignore_errors: yes 17 | 18 | - name: Wait additional 5 minutes as last resort (really slow env) 19 | wait_for_connection: 20 | timeout: 300 21 | when: not back_again2.changed 22 | register: back_again3 23 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/remove-tf-artifact-leftovers/tasks/clean_up_el8.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Remove rcmtools packages installed on the system 3 | ansible.builtin.shell: dnf list --installed | grep @rcmtools | awk '{print $1}' | xargs dnf remove -y 4 | ignore_errors: true 5 | - name: Remove rcmtools repo from the system 6 | ansible.builtin.file: 7 | path: "/etc/yum.repos.d/rcmtools.repo" 8 | state: absent 9 | 10 | - name: Remove qa-tools packages installed on the system 11 | ansible.builtin.shell: dnf list --installed | grep @.*qa-tools$ | awk '{print $1}' | xargs dnf remove -y 12 | ignore_errors: true 13 | - name: Remove qa-tools repo from the system 14 | ansible.builtin.file: 15 | path: "/etc/yum.repos.d/qa-tools.repo" 16 | state: absent 17 | 18 | - name: Remove beaker packages installed on the system 19 | ansible.builtin.shell: dnf list --installed | grep @beaker | awk '{print $1}' | xargs dnf remove -y 20 | ignore_errors: true 21 | - name: Remove beaker repo from the system 22 | ansible.builtin.file: 23 | path: "/etc/yum.repos.d/{{ item }}" 24 | state: absent 25 | with_items: 26 | - beaker-client.repo 27 | - beaker-client-testing.repo 28 | - beaker-harness.repo 29 | - beaker-tasks.repo 30 | - beakerlib-libraries.repo 31 | - rhel-CRB-latest.repo 32 | 33 | - name: Clean yum metadata 34 | ansible.builtin.shell: yum clean metadata 35 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/remove-tf-artifact-leftovers/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # After the artifact installation phase (which is done by the TF) there are 3 | # some third-party packages and repos left on the system. 4 | # Remove those packages and corresponding repositories. 5 | - include_tasks: clean_up_el7.yml 6 | when: ansible_facts['distribution_major_version'] == "7" 7 | - include_tasks: clean_up_el8.yml 8 | when: ansible_facts['distribution_major_version'] == "8" 9 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/update-ca-trust/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ### We need to update the ca trust in order to reach some of the internal URLs 3 | - include_tasks: update-ca-trust.yml 4 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/update-ca-trust/tasks/update-ca-trust.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get cacert_url 3 | shell: "grep -o 'CACERT_URL=.*' /var/tmp/.env | cut -d'=' -f2" 4 | register: CACERT_URL 5 | 6 | - name: Download the internal CA certificate 7 | get_url: 8 | url: "{{ CACERT_URL.stdout }}" 9 | dest: /etc/pki/ca-trust/source/anchors/Current-IT-Root-CAs.pem 10 | 11 | - name: Add the certificate to trusted CA's 12 | shell: update-ca-trust 13 | no_log: true 14 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/update-system/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: update-system.yml 3 | -------------------------------------------------------------------------------- /tests/ansible_collections/roles/update-system/tasks/update-system.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Update system 3 | yum: 4 | name: "*" 5 | state: latest 6 | # In case the package is already installed on the system (by user or CI system) 7 | # and the version of the package is not the latest in copr repo it would be 8 | # updated at this point. The package version would then differ from the intended one. 9 | exclude: convert2rhel 10 | register: update 11 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_check_data_collection.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def test_check_data_collection(): 5 | """ 6 | Verify that after conversion the convert2rhel.facts file is present. 7 | """ 8 | convert2rhel_facts_file = "/etc/rhsm/facts/convert2rhel.facts" 9 | assert os.path.exists(convert2rhel_facts_file) 10 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_delete_temp_folder.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def test_deleted_temporary_folder(): 5 | """ 6 | Verify the temporary folder "/var/lib/convert2rhel/" was successfully removed after the conversion. 7 | """ 8 | tmp_folder = "/var/lib/convert2rhel/" 9 | assert not os.path.exists(tmp_folder) 10 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_firewalld_errors.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def test_check_firewalld_errors(shell): 5 | """Verify that there are no errors in firewalld""" 6 | if shell("rpm -q firewalld").returncode == 0: 7 | shell("systemctl start firewalld") 8 | assert shell("journalctl -u firewalld | grep -i ERROR").returncode == 1 9 | else: 10 | pytest.skip("Skipping because firewalld package is not present on system.") 11 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_flag_system_as_converted.py: -------------------------------------------------------------------------------- 1 | import jsonschema 2 | 3 | from test_helpers.common_functions import load_json_schema 4 | 5 | 6 | C2R_MIGRATION_RESULTS_SCHEMA = load_json_schema(path="artifacts/c2r_migration_results_schema.json") 7 | C2R_RHSM_CUSTOM_FACTS_SCHEMA = load_json_schema(path="artifacts/c2r_facts_schema.json") 8 | 9 | C2R_MIGRATION_RESULTS = "/etc/migration-results" 10 | C2R_RHSM_CUSTOM_FACTS = "/etc/rhsm/facts/convert2rhel.facts" 11 | 12 | 13 | def test_flag_system_as_converted(shell): 14 | """ 15 | Verify, that the breadcrumbs file was created and corresponds to the JSON schema after the conversion. 16 | """ 17 | 18 | submgr_disabled_var = "SUBMGR_DISABLED_SKIP_CHECK_RHSM_CUSTOM_FACTS=1" 19 | query = shell(f"set | grep {submgr_disabled_var}").output 20 | 21 | data_json = load_json_schema(C2R_MIGRATION_RESULTS) 22 | 23 | # If some difference between generated json and its schema invoke exception 24 | try: 25 | jsonschema.validate(instance=data_json, schema=C2R_MIGRATION_RESULTS_SCHEMA) 26 | except Exception: 27 | print(data_json) 28 | raise 29 | 30 | # We need to validate the schema just in case the SUBMGR_DISABLED_SKIP_CHECK_RHSM_CUSTOM_FACTS 31 | # envar is not set (we might set the envar for example due to disabled submgr) 32 | if submgr_disabled_var not in query: 33 | data_json = load_json_schema(C2R_RHSM_CUSTOM_FACTS) 34 | 35 | # If some difference between generated json and its schema invoke exception 36 | try: 37 | jsonschema.validate(instance=data_json, schema=C2R_RHSM_CUSTOM_FACTS_SCHEMA) 38 | except Exception: 39 | print(data_json) 40 | raise 41 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_grub_default.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import pytest 4 | 5 | 6 | @pytest.mark.test_grub_default 7 | def test_grub_default(shell): 8 | """ 9 | After conversion check. 10 | Verify that the default grub title matches RHEL. 11 | Additionally verify that the kernel the system is booted into 12 | the one defined in the default entry. 13 | """ 14 | grub_default = shell("grubby --default-title").output.strip() 15 | running_kernel = shell("uname -r").output.strip() 16 | title_rgx = f"Red Hat Enterprise Linux(?: Server)? \\({running_kernel}\\)" 17 | assert re.match(title_rgx, grub_default) 18 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_logging_not_duplicated.py: -------------------------------------------------------------------------------- 1 | def test_verify_logging_is_not_duplicated(): 2 | """ 3 | Verify that the logfile does not contain duplicated lines. 4 | 5 | This function goes through the log file line by line 6 | and verifies the lines are unique and not duplicated. 7 | """ 8 | log_file = "/var/log/convert2rhel/convert2rhel.log" 9 | with open(log_file, "r") as log_file_data: 10 | previous_line = None 11 | for line in log_file_data: 12 | line = line.strip() 13 | if line != "": 14 | assert line != previous_line 15 | 16 | previous_line = line.strip() 17 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_rhel_kernel.py: -------------------------------------------------------------------------------- 1 | def test_rhel_kernel(shell): 2 | """ 3 | After conversion check. 4 | Verify that every installed kernel is Red Hat kernel. 5 | """ 6 | installed_kernels = shell("rpm -q --qf '%{NAME} %{VERSION}-%{RELEASE} %{VENDOR}\\n' kernel").output.split("\n") 7 | # Iterate over the list of installed_kernels and verify that every kernel is Red Hat one 8 | # We end up with an empty last item in the list due to a trailing whitespace, 9 | # therefore we only verify non-empty items in the list comprehension (`if kernel`) 10 | assert all("Red Hat" in kernel for kernel in installed_kernels if kernel) 11 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_rhel_subman.py: -------------------------------------------------------------------------------- 1 | def test_rhel_subscription_manager(shell): 2 | """ 3 | After conversion check. 4 | Verify that the subscription-manager installed by c2r has the Red Hat signature/ 5 | """ 6 | assert ( 7 | "199e2f91fd431d51" 8 | in shell( 9 | "rpm -q --qf '%|DSAHEADER?{%{DSAHEADER:pgpsig}}:" 10 | "{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{(none)}|}|' " 11 | "subscription-manager" 12 | ).output 13 | ) 14 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_yum_check.py: -------------------------------------------------------------------------------- 1 | def test_yum_check(shell): 2 | """ 3 | After conversion check verifying yum check is able to finis without any issues. 4 | """ 5 | assert shell("yum check").returncode == 0 6 | -------------------------------------------------------------------------------- /tests/integration/common/checks-after-conversion/test_yum_check_update.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.parametrize("package", ["kernel*"]) 5 | def test_yum_check_update(shell, package): 6 | """ 7 | After the conversion verify yum check-update does not return outdated package. 8 | """ 9 | assert package not in shell(f"yum check-update {package}").output 10 | -------------------------------------------------------------------------------- /tests/integration/common/utils/reboot-after-conversion/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Reboot the system after conversion 3 | description: | 4 | Typically for tests with full conversion, we need to reboot the system, 5 | to perform multiple checks after conversion. 6 | This suits only the purpose of rebooting the system. 7 | 8 | test: pytest -m reboot_after_conversion 9 | result: info 10 | order: 51 11 | -------------------------------------------------------------------------------- /tests/integration/common/utils/reboot-after-conversion/test_reboot.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pytest 4 | 5 | 6 | @pytest.mark.reboot_after_conversion 7 | def test_reboot(shell): 8 | if os.environ["TMT_REBOOT_COUNT"] == "0": 9 | shell("tmt-reboot -t 600") 10 | -------------------------------------------------------------------------------- /tests/integration/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Integration tests 3 | duration: 90m 4 | -------------------------------------------------------------------------------- /tests/integration/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.ruff] 2 | # Extend the `pyproject.toml` file in the parent directory... 3 | extend = "../../pyproject.toml" 4 | 5 | [tool.ruff.lint] 6 | ignore = [ 7 | "E402", # ignore import not at top level, we need this for the mocking 8 | ] 9 | -------------------------------------------------------------------------------- /tests/integration/test_helpers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oamg/convert2rhel/b762cdccf82524d2c93c006adb99d1f49cce3d43/tests/integration/test_helpers/__init__.py -------------------------------------------------------------------------------- /tests/integration/test_helpers/checks_nondestructive.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | 4 | import pytest 5 | 6 | from test_helpers.common_functions import get_log_file_data 7 | 8 | 9 | @pytest.fixture(autouse=True) 10 | def check_validate_deprecated_envar_message(): 11 | """ 12 | Check fixture. 13 | Validate that the warning message for deprecated environment variables is present, 14 | if the respective environment variable is used. 15 | """ 16 | 17 | yield 18 | 19 | if "C2R_TESTS_NONDESTRUCTIVE" in os.environ: 20 | missing_envar_messages = [] 21 | log_file_data = get_log_file_data() 22 | for key in os.environ.keys(): 23 | if re.match("CONVERT2RHEL_", key): 24 | if not re.search(f"The environment variable {key} is deprecated", log_file_data): 25 | missing_envar_messages.append(key) 26 | if missing_envar_messages: 27 | pytest.fail(f"The warning message for deprecated envars {missing_envar_messages} is not not present.") 28 | -------------------------------------------------------------------------------- /tests/integration/test_helpers/shell.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | from collections import namedtuple 4 | 5 | import click 6 | 7 | 8 | def live_shell(): 9 | """ 10 | Live shell. 11 | Callable directly. 12 | """ 13 | 14 | def factory(command, silent=False, hide_command=False): 15 | if silent: 16 | click.echo("This shell call is set to silent=True, therefore no output will be printed.") 17 | if hide_command: 18 | click.echo("This shell call is set to hide_command=True, so it won't show the called command.") 19 | if not silent and not hide_command: 20 | click.echo( 21 | "\nExecuting a command:\n{}\n\n".format(command), 22 | color="green", 23 | ) 24 | # pylint: disable=consider-using-with 25 | # Popen is a context-manager in python-3.2+ 26 | process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 27 | output = "" 28 | for line in iter(process.stdout.readline, b""): 29 | output += line.decode() 30 | if not silent: 31 | click.echo(line.decode().rstrip("\n")) 32 | returncode = process.wait() 33 | return namedtuple("Result", ["returncode", "output"])(returncode, output) 34 | 35 | return factory 36 | -------------------------------------------------------------------------------- /tests/integration/test_helpers/vars.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from dotenv import dotenv_values 4 | 5 | 6 | TEST_VARS = dotenv_values("/var/tmp/.env") 7 | SAT_REG_FILE = dotenv_values("/var/tmp/.env_sat_reg") 8 | SYSTEM_RELEASE_ENV = os.environ["SYSTEM_RELEASE_ENV"] 9 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_activation_key.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_activation_key_conversion(convert2rhel): 5 | """ 6 | Basic conversion method using the RHSM activation key and organization for registration. 7 | """ 8 | with convert2rhel( 9 | "-y --serverurl {} -k {} -o {} --debug".format( 10 | TEST_VARS["RHSM_SERVER_URL"], 11 | TEST_VARS["RHSM_SCA_KEY"], 12 | TEST_VARS["RHSM_SCA_ORG"], 13 | ) 14 | ) as c2r: 15 | c2r.expect("Conversion successful!") 16 | assert c2r.exitstatus == 0 17 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_config_file.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from collections import namedtuple 4 | 5 | from conftest import TEST_VARS 6 | 7 | 8 | Config = namedtuple("Config", "path content") 9 | 10 | 11 | def create_files(config): 12 | for cfg in config: 13 | with open(os.path.expanduser(cfg.path), mode="w") as handler: 14 | handler.write(cfg.content) 15 | 16 | os.chmod(os.path.expanduser(cfg.path), 0o600) 17 | 18 | 19 | def remove_files(config): 20 | for cfg in config: 21 | os.remove(os.path.expanduser(cfg.path)) 22 | 23 | 24 | def test_conversion_with_config_file(convert2rhel): 25 | """ 26 | Use config file to feed the credentials for the registration and verify a successful conversion. 27 | """ 28 | activation_key = "[subscription_manager]\nactivation_key = {}\norg = {}".format( 29 | TEST_VARS["RHSM_SCA_KEY"], TEST_VARS["RHSM_SCA_ORG"] 30 | ) 31 | config = [Config("~/.convert2rhel.ini", activation_key)] 32 | create_files(config) 33 | 34 | with convert2rhel("-y --serverurl {} --debug".format(TEST_VARS["RHSM_SERVER_URL"])) as c2r: 35 | c2r.expect("DEBUG - Found activation_key in subscription_manager") 36 | c2r.expect("DEBUG - Found org in subscription_manager") 37 | c2r.expect("Conversion successful!") 38 | 39 | assert c2r.exitstatus == 0 40 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_custom_repos.py: -------------------------------------------------------------------------------- 1 | from test_helpers.common_functions import SystemInformationRelease, get_custom_repos_names 2 | 3 | 4 | def test_system_conversion_using_custom_repositories(shell, convert2rhel): 5 | """ 6 | Conversion method with disabled subscription manager/RHSM and enabled 'custom' repositories. 7 | Usually we use the RHSM to enable the repositories `rhel-$releasever-server`. 8 | In this case we disable the RHSM and we need to provide our choice of repositories to be enabled. 9 | The repositories enabled in this scenario are 10 | {rhel7: [server rpms, extras rpms, optional rpms], rhel8: [[eus-]?baseos], [eus-]?appstream}. 11 | """ 12 | # Join the --enablerepo on whitespace 13 | enable_repo_opt_c2r = " ".join(f"--enablerepo {repo}" for repo in get_custom_repos_names()) 14 | 15 | if SystemInformationRelease.is_eus: 16 | shell("touch /eus_repos_used") 17 | 18 | with convert2rhel("-y --no-rhsm {} --debug".format(enable_repo_opt_c2r)) as c2r: 19 | c2r.expect("Conversion successful!") 20 | assert c2r.exitstatus == 0 21 | 22 | enable_repo_opt_yum = " ".join(f"--enable {repo}" for repo in get_custom_repos_names()) 23 | shell("yum-config-manager {}".format(enable_repo_opt_yum)) 24 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_one_key_satellite.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.parametrize("fixture_satellite", ["RHEL7_AND_CENTOS7_SAT_REG"], indirect=True) 5 | def test_satellite_system_conversion_using_one_key(shell, convert2rhel, fixture_satellite, remove_repositories): 6 | """ 7 | Conversion method using the Satellite credentials for a registration. 8 | The system is pre-registered to the Satellite instance prior to the conversion. 9 | We use one activation key containing both the original OS and RHEL repositories. 10 | """ 11 | # We need to enable the current system repositories prior to the conversion 12 | shell("subscription-manager repos --enable=*") 13 | 14 | with convert2rhel("-y --debug") as c2r: 15 | c2r.expect("Conversion successful!") 16 | assert c2r.exitstatus == 0 17 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_pre_registered.py: -------------------------------------------------------------------------------- 1 | def test_pre_registered_system_conversion(convert2rhel, pre_registered): 2 | with convert2rhel("-y --debug") as c2r: 3 | c2r.expect("Conversion successful!") 4 | assert c2r.exitstatus == 0 5 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_rhsm.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_rhsm_conversion(convert2rhel): 5 | with convert2rhel( 6 | "-y --serverurl {} --username {} --password {} --debug".format( 7 | TEST_VARS["RHSM_SERVER_URL"], 8 | TEST_VARS["RHSM_SCA_USERNAME"], 9 | TEST_VARS["RHSM_SCA_PASSWORD"], 10 | ) 11 | ) as c2r: 12 | c2r.expect("Conversion successful!") 13 | assert c2r.exitstatus == 0 14 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_rhsm_els.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_rhsm_with_els_system_conversion(convert2rhel, shell, fixture_subman): 5 | """ 6 | Verify that Convert2RHEL is working properly when ELS repositories are used during the conversion. 7 | Verify that the correct repositories are enabled after the conversion (in one of the check-after-conversion tests). 8 | """ 9 | 10 | # Mark the system so the check for the enabled repos after the conversion handles this special case 11 | shell("touch /els_repos_used") 12 | 13 | with convert2rhel( 14 | "-y --username {} --password {} --debug --els".format( 15 | TEST_VARS["RHSM_SCA_USERNAME"], 16 | TEST_VARS["RHSM_SCA_PASSWORD"], 17 | ) 18 | ) as c2r: 19 | c2r.expect_exact("Enabling RHEL repositories:") 20 | c2r.expect_exact("rhel-7-server-els-rpms") 21 | c2r.expect_exact("Conversion successful!") 22 | assert c2r.exitstatus == 0 23 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_rhsm_eus.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS, SystemInformationRelease 2 | 3 | 4 | def test_rhsm_with_eus_system_conversion(convert2rhel, shell): 5 | """ 6 | Verify that Convert2RHEL is working properly when EUS repositories are used during the conversion. 7 | Only on EUS versions (8.6, 8.8, ...) it is possible to do EUS conversion. 8 | Verify that the correct repositories are enabled after the conversion. 9 | """ 10 | 11 | # Mark the system so the check for the enabled repos after the conversion handles this special case 12 | shell("touch /eus_repos_used") 13 | 14 | with convert2rhel( 15 | "-y --serverurl {} --username {} --password {} --debug --eus".format( 16 | TEST_VARS["RHSM_SERVER_URL"], 17 | TEST_VARS["RHSM_SCA_USERNAME"], 18 | TEST_VARS["RHSM_SCA_PASSWORD"], 19 | ) 20 | ) as c2r: 21 | c2r.expect_exact("Enabling RHEL repositories:") 22 | c2r.expect_exact(f"rhel-{SystemInformationRelease.version.major}-for-x86_64-baseos-eus-rpms") 23 | c2r.expect_exact(f"rhel-{SystemInformationRelease.version.major}-for-x86_64-appstream-eus-rpms") 24 | c2r.expect_exact("Conversion successful!") 25 | assert c2r.exitstatus == 0 26 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/conversion-method/test_satellite.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_satellite_conversion(convert2rhel, fixture_satellite): 5 | """ 6 | Conversion method using the Satellite credentials for registration. 7 | Use the provided curl command to download the registration script to a file, 8 | then run the registration script file. 9 | """ 10 | with convert2rhel( 11 | "-y -k {} -o {} --debug".format( 12 | TEST_VARS["SATELLITE_KEY"], 13 | TEST_VARS["SATELLITE_ORG"], 14 | ) 15 | ) as c2r: 16 | pass 17 | assert c2r.exitstatus == 0 18 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/isolated-system-conversion/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Convert isolated system 3 | 4 | description: | 5 | Convert systems that have no access to the Internet. 6 | This is done by dnsmasq configure to the Satellite only, everything else is resolved to the 7 | localhost. 8 | This test requires having the repositories of the original OS available in the Satellite server. 9 | 10 | tag+: 11 | - isolated-system-conversion 12 | - satellite 13 | 14 | /isolated_system_conversion: 15 | test: pytest -m test_isolated_system_conversion 16 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/isolated-system-conversion/test_isolated_system_conversion.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_isolated_system_conversion(convert2rhel): 5 | """Test converting systems not connected to the Internet but requiring sub-mgr (e.g. managed by Satellite).""" 6 | 7 | with convert2rhel( 8 | "-y -k {} -o {} --debug".format( 9 | TEST_VARS["SATELLITE_KEY"], 10 | TEST_VARS["SATELLITE_ORG"], 11 | ) 12 | ) as c2r: 13 | pass 14 | assert c2r.exitstatus == 0 15 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Destructive plans 3 | 4 | description+: | 5 | Set of destructive plans performing full conversion. 6 | Plan usually consist of a preparation phase preparing the system for the main test run. 7 | The reboot is performed by using tmt-reboot function with help of TMT_REBOOT_COUNT environment variable. 8 | After rebooting to RHEL a set of after conversion checks is run. 9 | For some plans there might be some checks excluded. 10 | 11 | tag+: 12 | - destructive 13 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/single-yum-transaction/install_dependency_packages.py: -------------------------------------------------------------------------------- 1 | from conftest import SystemInformationRelease 2 | 3 | 4 | def test_install_dependency_packages(shell): 5 | """ 6 | Having certain packages installed used to cause conversion failures - namely yum dependency resolution errors. 7 | 8 | This test verifies that having these packages pre-installed does not cause a failure anymore 9 | """ 10 | 11 | dependency_pkgs = [ 12 | "abrt-retrace-client", # OAMG-4447 13 | "libreport-cli", # OAMG-4447 14 | "ghostscript-devel", # Case 02855547 15 | "python2-dnf", # OAMG-4690 16 | "python2-dnf-plugins-core", # OAMG-4690 17 | "redhat-lsb-trialuse", # OAMG-4942 18 | "ldb-tools", # OAMG-4941 19 | "gcc-c++", # OAMG-6136 20 | "python-requests", # OAMG-4936 21 | ] 22 | if SystemInformationRelease.version.major == 8: 23 | if SystemInformationRelease.distribution == "oracle": 24 | dependency_pkgs = [ 25 | "iwl7260-firmware", # RHELC-567 26 | "iwlax2xx-firmware", # RHELC-567 - causing problems during the conversion on OL8 27 | ] 28 | else: 29 | dependency_pkgs = [ 30 | "python39-psycopg2-debug", # OAMG-5239, OAMG-4944 - package not available on Oracle Linux 8 31 | ] 32 | 33 | # installing dependency packages 34 | assert shell("yum install -y {}".format(" ".join(dependency_pkgs))).returncode == 0 35 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/single-yum-transaction/install_multilib_packages.py: -------------------------------------------------------------------------------- 1 | def test_install_multilib_packages(shell): 2 | """Install multilib packages.""" 3 | 4 | assert ( 5 | shell( 6 | "yum install iwl7260-firmware accel-config*.i686 libreport-cli ModemManager* ModemManager*.i686 -y" 7 | ).returncode 8 | == 0 9 | ) 10 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/single-yum-transaction/install_ntp_and_remove_dependency.py: -------------------------------------------------------------------------------- 1 | from conftest import SYSTEM_RELEASE_ENV 2 | 3 | 4 | def test_install_ntp_and_remove_dependency(shell): 5 | """Install NTP package and remove one dependency.""" 6 | 7 | if "oracle-7" in SYSTEM_RELEASE_ENV: 8 | assert shell("yum install ntp -y").returncode == 0 9 | assert shell("rpm -e --nodeps autogen-libopts").returncode == 0 10 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/single-yum-transaction/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Single yum transaction 3 | 4 | description: | 5 | Handle the unified yum transactions so that it handles packages without 6 | error. Previous iterations used a lot of different steps, whereas now it is 7 | one transaction that can be rolled back more easily. 8 | 9 | Verify that packages got upgraded by the end of conversion instead of 10 | reinstalled/downgraded. 11 | 12 | 13 | link: 14 | - https://issues.redhat.com/browse/RHELC-576 15 | - https://issues.redhat.com/browse/RHELC-899 16 | 17 | 18 | /single_yum_transaction: 19 | test: pytest -m test_single_yum_transaction 20 | 21 | /packages_upgraded_after_conversion: 22 | test: pytest -m test_packages_upgraded_after_conversion 23 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/single-yum-transaction/remove_excld_pkgs_from_config.py: -------------------------------------------------------------------------------- 1 | from conftest import SYSTEM_RELEASE_ENV 2 | 3 | 4 | def test_remove_excluded_pkgs_from_config(shell): 5 | """Remove some excluded packages from the CentOS Linux 7 config file. 6 | 7 | That means Convert2RHEL won't remove them before the main conversion transaction. 8 | """ 9 | 10 | if "centos-7" in SYSTEM_RELEASE_ENV: 11 | assert shell("sed -i '/mod_ldap/d' /usr/share/convert2rhel/configs/centos-7-x86_64.cfg").returncode == 0 12 | assert shell("sed -i '/mod_proxy_html/d' /usr/share/convert2rhel/configs/centos-7-x86_64.cfg").returncode == 0 13 | 14 | # make sure that the packages we don't want convert2rhel to remove are present on the test system 15 | assert shell("yum install mod_ldap mod_proxy_html -y").returncode == 0 16 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/single-yum-transaction/test_single_yum_transaction.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS, SystemInformationRelease 2 | 3 | 4 | def test_single_yum_transaction(convert2rhel, shell): 5 | """Run the conversion using the single yum transaction. 6 | 7 | This will run the conversion up until the point of the single yum 8 | transaction package replacements. 9 | """ 10 | pkgmanager = "dnf" 11 | 12 | if SystemInformationRelease.version.major == 7: 13 | pkgmanager = "yum" 14 | 15 | with convert2rhel( 16 | "-y --serverurl {} --username {} --password {} --debug".format( 17 | TEST_VARS["RHSM_SERVER_URL"], 18 | TEST_VARS["RHSM_SCA_USERNAME"], 19 | TEST_VARS["RHSM_SCA_PASSWORD"], 20 | ) 21 | ) as c2r: 22 | c2r.expect("no modifications to the system will happen this time.", timeout=1200) 23 | c2r.expect("Successfully validated the {} transaction set.".format(pkgmanager), timeout=600) 24 | c2r.expect("This process may take some time to finish.", timeout=300) 25 | c2r.expect("System packages replaced successfully.", timeout=900) 26 | c2r.expect("Conversion successful!") 27 | assert c2r.exitstatus == 0 28 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/yum-distro-sync/add-extras-repo/centos7_extras.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Add CentOS extras repo 4 | yum_repository: 5 | name: centos7-extras 6 | description: CentOS extras for $basearch 7 | baseurl: https://vault.centos.org/centos/7/extras/$basearch/ 8 | gpgcheck: no 9 | enabled: yes 10 | file: centos7-extras 11 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/yum-distro-sync/add-extras-repo/centos8_extras.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Add CentOS extras repo 4 | yum_repository: 5 | name: centos8-extras 6 | description: CentOS extras for $basearch 7 | baseurl: https://vault.centos.org/centos/8/extras/$basearch/os/ 8 | gpgcheck: no 9 | enabled: yes 10 | file: centos8-extras 11 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/yum-distro-sync/add-extras-repo/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | gather_facts: yes 4 | become: false 5 | - import_playbook: centos7_extras.yml 6 | when: ansible_facts['distribution_major_version'] == "7" 7 | - import_playbook: centos8_extras.yml 8 | when: ansible_facts['distribution_major_version'] in ["8", "9"] 9 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/yum-distro-sync/install_problematic_package.py: -------------------------------------------------------------------------------- 1 | from conftest import SYSTEM_RELEASE_ENV 2 | 3 | 4 | def test_install_problematic_package(shell): 5 | """ 6 | Install a package, which is in CentOS repos and is not present in RHEL repositories. 7 | The package in question (cpaste) is from the CentOS Extras repo which is enabled by default on 8 | CentOS systems. 9 | 10 | When the test starts failing we will need to change the selected package. 11 | """ 12 | 13 | # There are packages some packages on the artemis CentOS-8 guest, that need to be removed 14 | # so `yum distro-sync` will fail on cpaste. 15 | # If not removed, the `yum distro-sync` would not fail (yum return 0 when at least one package is ok) 16 | if "centos-8" in SYSTEM_RELEASE_ENV: 17 | assert ( 18 | shell("yum remove python2-pip python2-pip-wheel python2-setuptools python2-setuptools-wheel -y").returncode 19 | == 0 20 | ) 21 | assert shell("yum install -y cpaste").returncode == 0 22 | -------------------------------------------------------------------------------- /tests/integration/tier0/destructive/yum-distro-sync/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | yum distro-sync edge-cases 3 | 4 | description: | 5 | Verify the 'yum distro-sync' command edge-cases when given packages are not in the enabled repositories. 6 | 7 | link: 8 | - verifies: https://issues.redhat.com/browse/RHELC-150 9 | 10 | /yum_distro_sync: 11 | test: pytest -m test_yum_distro_sync 12 | 13 | 14 | #TODO(danmyway) merge with single-yum-transaction 15 | -------------------------------------------------------------------------------- /tests/integration/tier0/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Tier0 tests 3 | 4 | description+: | 5 | Critical set of tests/plans to be run for each upstream PR 6 | before merge commit to the main branch. 7 | 8 | tier: 0 9 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/application-lock/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Application lock checks 3 | description: | 4 | Verify that an attempt to run a second instance of convert2rhel 5 | while an instance is already running fails. 6 | 7 | tier: 0 8 | 9 | tag+: 10 | - application-lock 11 | - sanity 12 | 13 | /simultaneous_runs: 14 | summary+: | 15 | Simultaneous runs 16 | description+: | 17 | Verify that running convert2rhel locks out other instances. 18 | Additionally validate that the logfile did not get overwritten by the second invocation's output. 19 | 1/ Invoke convert2rhel, wait on data collection acknowledgement prompt. 20 | 2/ Invoke second instance of convert2rhel, observe warning and the utility exit. 21 | 3/ Exit the first run of convert2rhel. 22 | 4/ Validate that the logfile did not get overwritten by the second invocation's output. 23 | 5/ Invoke third instance of convert2rhel; with the previous instances dead, the third instance should be allowed to run. 24 | 6/ Exit the utility on the first prompt. 25 | tag+: 26 | - simultaneous-runs 27 | test: | 28 | pytest -m test_simultaneous_runs 29 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/application-lock/test_application_lock.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | def test_simultaneous_runs(convert2rhel): 5 | """ 6 | Verify that running convert2rhel locks out other instances. 7 | Additionally validate that the logfile did not get overwritten by the second invocation's output. 8 | 1/ Invoke convert2rhel, wait on data collection acknowledgement prompt. 9 | 2/ Invoke second instance of convert2rhel, observe warning and the utility exit. 10 | 3/ Exit the first run of convert2rhel. 11 | 4/ Validate that the logfile did not get overwritten by the second invocation's output. 12 | 5/ Invoke third instance of convert2rhel; with the previous instances dead, the third instance should be allowed to run. 13 | 6/ Exit the utility on the first prompt. 14 | """ 15 | 16 | def _run_second_instance(): 17 | """ 18 | Helper function initiating a second simultaneous run of convert2rhel. 19 | Expect exit immediately. 20 | """ 21 | with convert2rhel("--debug") as c2r_two: 22 | c2r_two.expect("Another copy of convert2rhel is running.") 23 | assert c2r_two.exitstatus == 1 24 | 25 | # Invoke a first instance 26 | with convert2rhel("--debug") as c2r_one: 27 | c2r_one.expect("Continue with the system conversion?") 28 | # Invoke the helper function with a second run 29 | _run_second_instance() 30 | # Exit the first run 31 | c2r_one.sendline("n") 32 | assert c2r_one.exitstatus == 1 33 | 34 | c2r_log = "/var/log/convert2rhel/convert2rhel.log" 35 | pattern = r"DEBUG - /var/run/lock/convert2rhel\.pid PID \d+ unlocked" 36 | # Verify the log file did not get replaced by the second utility invocation 37 | with open(c2r_log, "r") as logfile: 38 | data = logfile.read() 39 | assert re.search(pattern, data) 40 | 41 | # Run for the third time to make sure, the application lock is removed 42 | with convert2rhel("--debug") as c2r_three: 43 | c2r_three.expect("Continue with the system conversion?") 44 | c2r_three.sendline("n") 45 | assert c2r_three.exitstatus == 1 46 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/assessment-report/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Pre-Assessment report 3 | 4 | description+: | 5 | Verify that the pre-assessment report is working as intended. 6 | Verify the report is also created as json file 7 | and validate the json report against its given json schema. 8 | Verify the report is also created as a txt file. 9 | 10 | tier: 0 11 | 12 | tag+: 13 | - pre-assessment-report 14 | 15 | /failures_and_skips_in_report: 16 | summary+: | 17 | Verify that some actions failures and skips appeared in the report. 18 | description+: | 19 | Verify that the assessment report contains the following headers and messages: 20 | Error header, skip header, success header. 21 | Also verify the message severity ordering. 22 | 23 | Verify the report is created in /var/log/convert2rhel/convert2rhel-pre-conversion.json, 24 | and it corresponds to its respective schema. 25 | tag+: 26 | - failed-report 27 | test: | 28 | pytest -m test_failures_and_skips_in_report 29 | 30 | /successful_report: 31 | summary+: | 32 | Verify that the report was successful. 33 | description+: | 34 | Verify that the conversion will proceed until the point of no return 35 | and then, output the report to the user. 36 | tag+: 37 | - success-report 38 | - sanity 39 | test: | 40 | pytest -m test_successful_report 41 | 42 | /convert_successful_report: 43 | summary+: | 44 | Verify that the `convert` subcommand works. 45 | description+: | 46 | Validate that calling the `convert` subcommand works. 47 | Verify the assessment report does not contain any header: 48 | Success header, Error header, Skip header. 49 | NOTE: Without the analyze subcommand the convert2rhel does not 50 | pollute the output with Success header and checks. 51 | tag+: 52 | - convert-success-report 53 | test: | 54 | pytest -m test_convert_method_successful_report 55 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/custom-repository/files/rhel7.repo: -------------------------------------------------------------------------------- 1 | [rhel-7-server-rpms] 2 | name=RHEL 7.9 for $basearch 3 | baseurl=https://rhsm-pulp.corp.redhat.com/content/dist/rhel/server/7/$releasever/$basearch/os/ 4 | gpgcheck=0 5 | enabled=0 6 | 7 | [rhel-7-server-optional-rpms] 8 | name=RHEL 7.9 Optional for $basearch 9 | baseurl=https://rhsm-pulp.corp.redhat.com/content/dist/rhel/server/7/$releasever/$basearch/optional/os/ 10 | gpgcheck=0 11 | enabled=0 12 | 13 | [rhel-7-server-extras-rpms] 14 | name=RHEL 7 Extras for $basearch 15 | baseurl=https://rhsm-pulp.corp.redhat.com/content/dist/rhel/server/7/$releasever/$basearch/extras/os/ 16 | gpgcheck=0 17 | enabled=0 18 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/custom-repository/files/rhel8-eus.repo: -------------------------------------------------------------------------------- 1 | [rhel-8-for-x86_64-baseos-eus-rpms] 2 | name=RHEL 8 BaseOS for $basearch 3 | baseurl=https://rhsm-pulp.corp.redhat.com/content/eus/rhel8/$releasever/$basearch/baseos/os/ 4 | gpgcheck=0 5 | enabled=0 6 | 7 | [rhel-8-for-x86_64-appstream-eus-rpms] 8 | name=RHEL 8 AppStream for $basearch 9 | baseurl=https://rhsm-pulp.corp.redhat.com/content/eus/rhel8/$releasever/$basearch/appstream/os/ 10 | gpgcheck=0 11 | enabled=0 12 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/custom-repository/files/rhel8.repo: -------------------------------------------------------------------------------- 1 | [rhel-8-for-x86_64-baseos-rpms] 2 | name=RHEL 8 BaseOS for $basearch 3 | baseurl=https://rhsm-pulp.corp.redhat.com/content/dist/rhel8/$releasever/$basearch/baseos/os/ 4 | gpgcheck=0 5 | enabled=0 6 | 7 | [rhel-8-for-x86_64-appstream-rpms] 8 | name=RHEL 8 AppStream for $basearch 9 | baseurl=https://rhsm-pulp.corp.redhat.com/content/dist/rhel8/$releasever/$basearch/appstream/os/ 10 | gpgcheck=0 11 | enabled=0 12 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/custom-repository/files/rhel9-eus.repo: -------------------------------------------------------------------------------- 1 | [rhel-9-for-x86_64-baseos-eus-rpms] 2 | name=RHEL 9 BaseOS for $basearch 3 | baseurl=https://rhsm-pulp.corp.redhat.com/content/eus/rhel9/$releasever/$basearch/baseos/os/ 4 | gpgcheck=0 5 | enabled=0 6 | 7 | [rhel-9-for-x86_64-appstream-eus-rpms] 8 | name=RHEL 9 AppStream for $basearch 9 | baseurl=https://rhsm-pulp.corp.redhat.com/content/eus/rhel9/$releasever/$basearch/appstream/os/ 10 | gpgcheck=0 11 | enabled=0 12 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/custom-repository/files/rhel9.repo: -------------------------------------------------------------------------------- 1 | [rhel-9-for-x86_64-baseos-rpms] 2 | name=RHEL 9 BaseOS for $basearch 3 | baseurl=https://rhsm-pulp.corp.redhat.com/content/dist/rhel9/$releasever/$basearch/baseos/os/ 4 | gpgcheck=0 5 | enabled=0 6 | 7 | [rhel-9-for-x86_64-appstream-rpms] 8 | name=RHEL 9 AppStream for $basearch 9 | baseurl=https://rhsm-pulp.corp.redhat.com/content/dist/rhel9/$releasever/$basearch/appstream/os/ 10 | gpgcheck=0 11 | enabled=0 12 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/custom-repository/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Enable custom repositories 3 | description: | 4 | Verify scenarios with enabled custom repositories and subscription-manager disabled. 5 | 6 | tier: 0 7 | 8 | tag+: 9 | - custom-repository 10 | 11 | 12 | /custom_valid_repo_provided: 13 | summary+: | 14 | Valid custom repository enabled 15 | description+: | 16 | Provide valid custom repository and verify that the conversion proceeds without issues. 17 | tag+: 18 | - custom-valid-repo-provided 19 | test: | 20 | pytest -m test_custom_valid_repo_without_rhsm 21 | 22 | /custom_invalid_repo_provided: 23 | summary+: | 24 | Invalid custom repository enabled 25 | description+: | 26 | Provide invalid values for custom repository options and verify 27 | that the CUSTOM_REPOSITORIES_ARE_VALID.UNABLE_TO_ACCESS_REPOSITORIES is raised. 28 | tag+: 29 | - custom-invalid-repo-provided 30 | test: | 31 | pytest -m test_custom_invalid_repo_without_rhsm 32 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/custom-repository/test_custom_repository.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from conftest import SystemInformationRelease 4 | from test_helpers.common_functions import get_custom_repos_names 5 | 6 | 7 | @pytest.fixture(scope="function") 8 | def set_custom_repository_files(shell): 9 | """ 10 | Fixture. 11 | Set up custom repositories. 12 | Tear down after the test. 13 | """ 14 | repo_file_name = f"rhel{SystemInformationRelease.version.major}" 15 | if SystemInformationRelease.is_eus: 16 | repo_file_name += "-eus" 17 | 18 | assert shell(f"cp files/{repo_file_name}.repo /etc/yum.repos.d/").returncode == 0 19 | 20 | yield 21 | 22 | assert shell(f"rm -f /etc/yum.repos.d/{repo_file_name}.repo").returncode == 0 23 | 24 | 25 | def test_custom_valid_repo_without_rhsm(convert2rhel, set_custom_repository_files): 26 | """ 27 | Verify that --enablerepo is not skipped when subscription-manager is disabled. 28 | Verify that the passed repositories are accessible. 29 | """ 30 | # Join the --enablerepo on whitespace 31 | enable_repo_opt = " ".join(f"--enablerepo {repo}" for repo in get_custom_repos_names()) 32 | 33 | with convert2rhel(f"-y --no-rhsm {enable_repo_opt} --debug", unregister=True) as c2r: 34 | c2r.expect("The repositories passed through the --enablerepo option are all accessible.") 35 | c2r.sendcontrol("c") 36 | 37 | assert c2r.exitstatus == 1 38 | 39 | 40 | def test_custom_invalid_repo_without_rhsm(shell, convert2rhel): 41 | """ 42 | Verify that --enablerepo is not skipped when subscription-manager is disabled. 43 | Verify the conversion will raise CUSTOM_REPOSITORIES_ARE_VALID.UNABLE_TO_ACCESS_REPOSITORIES 44 | with invalid repository passed. 45 | Make sure that after failed repo check there is a kernel installed. 46 | """ 47 | with convert2rhel( 48 | "-y --no-rhsm --enablerepo fake-rhel-repo-1 --enablerepo fake-rhel-repo-2 --debug", unregister=True 49 | ) as c2r: 50 | c2r.expect("CUSTOM_REPOSITORIES_ARE_VALID::UNABLE_TO_ACCESS_REPOSITORIES") 51 | 52 | assert c2r.exitstatus == 2 53 | 54 | assert shell("rpm -q kernel").returncode == 0 55 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/cve-2022-1662/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Verify the 2022-1662 CVE fixes 3 | description: | 4 | 2022-1662 CVE fixes leaking password and activation key 5 | to the command line when passing the value to subscription manager. 6 | 7 | tier: 0 8 | 9 | tag+: 10 | - cve-2022-1662 11 | - sanity 12 | 13 | /passing_password_to_submgr: 14 | summary+: | 15 | Password not leaked 16 | description+: | 17 | Verify that the password does not get leaked when passed to the subscription manager. 18 | tag+: 19 | - passing-password-to-submgr 20 | test: | 21 | pytest -m test_passing_password_to_submgr_obfuscated 22 | 23 | /passing_activation_key_to_submgr: 24 | summary+: | 25 | Activation key not leaked 26 | description+: | 27 | Verify that the activation key does not get leaked when passed to the subscription manager. 28 | tag+: 29 | - passing-activation-key-to-submgr 30 | test: | 31 | pytest -m test_passing_activation_key_to_submgr_obfuscated 32 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/duplicate-pkgs/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Duplicate pkgs installed on the system 3 | description+: | 4 | Verify that the conversion does not crash when the same 5 | package (of different version) is installed on the system. 6 | Verify that the proper inhibitor is raised. 7 | 8 | enabled: false 9 | 10 | /duplicate-pkgs: 11 | link: https://issues.redhat.com/browse/RHELC-1070 12 | adjust+: 13 | - enabled: true 14 | when: distro == centos-7, oracle-7 15 | because: | 16 | The bug is reproducible only on EL7 distros. 17 | On EL8 the issue is handled by the DNF itself. 18 | tag+: 19 | - test-duplicate-pkgs 20 | test: | 21 | pytest -m test_duplicate_packages_installed 22 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/els/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Verify the ELS candidates are handled correctly 3 | 4 | tag+: 5 | - els 6 | 7 | enabled: false 8 | 9 | adjust+: 10 | enabled: true 11 | when: distro == centos-7, oracle-7 12 | because: Only RHEL 7.9 has the ELS phase 13 | 14 | /els_enablement: 15 | description: | 16 | Test verifying correct behavior when converting ELS candidates. 17 | ELS_RELEASE_DATE in convert2rhel/systeminfo.py is modified to mock the different scenarios. 18 | Verified scenarios (handled by pytest parametrization): 19 | 1/ The system is considered as a non-ELS. This is done by modifying the major system version 20 | in the els.py file. 21 | The --els option is used in the command. Only regular (non-els) repoids should be enabled. 22 | 2/ The start date of the ELS phase is set far to the past to simulate the ELS phase began. 23 | The --els option *is used*. 24 | The report is expected to print out a WARNING and advise to use the --els option. 25 | tag+: 26 | - test-els-enablement 27 | test: | 28 | pytest -m test_els_enablement 29 | 30 | /non_els_account: 31 | description: | 32 | Verify that Convert2RHEL is working properly when ELS repositories are not available for conversions 33 | (the account does not have the ELS SKU available) to RHEL ELS version (7.9) 34 | and the --els option is provided. The regular repositories should be enabled as a fallback option. 35 | We're deliberately using SCA disabled account for this scenario. 36 | tag+: 37 | - test-rhsm-non-els-account 38 | - non-sca 39 | test: | 40 | pytest -m test_rhsm_non_els_account 41 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/enabled-repositories-after-analysis/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Verify repositories stay enabled after analysis 3 | 4 | tag+: 5 | - non-destructive 6 | - satellite 7 | enabled: false 8 | adjust+: 9 | enabled: true 10 | when: distro == centos-7 11 | because: currently we have satellite key only for CentOS7 12 | /enabled_repositories_after_analysis: 13 | description: | 14 | This test will perform the following operations: 15 | - Collect the enabled repositories prior to the analysis start 16 | - Run the analysis and assert that we successfully enabled the RHSM 17 | repositories 18 | - Collect the enabled repositories after the tool run to compare 19 | with the repositories prior to the analysis 20 | 21 | tag+: 22 | - test-enabled-repositories-after-analysis 23 | test: | 24 | pytest -m test_enabled_repositories_after_analysis 25 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/eus/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Verify the EUS releases are treated correctly 3 | 4 | tag+: 5 | - eus 6 | 7 | enabled: false 8 | 9 | adjust+: 10 | enabled: true 11 | when: distro == alma-8.8, rocky-8.8 12 | because: The only consistently relevant EUS releases are Alma and Rocky. 13 | 14 | /eus_enablement: 15 | description: | 16 | Test verifying correct behavior when converting EUS candidates. 17 | EUS_MINOR_VERISONS mapping in convert2rhel/systeminfo.py is modified to mock the different scenarios. 18 | Verified scenarios (handled by pytest parametrization): 19 | 1/ The system is considered as a non-EUS. This is done by removing the 8.8 version from the mapping file 20 | (note that this workaround works only on 8.8 systems). 21 | The --eus option is used in the command. Only regular (non-eus) repoids should be enabled. 22 | 2/ The start date of the EUS phase is set far to the future to simulate the EUS phase 23 | did not start yet. 24 | The --eus option *is not used* and regular repoids enablement is expected. 25 | 3/ The start date of the EUS phase is set far to the future to simulate the EUS phase 26 | did not start yet. 27 | The --eus option *is used* and EUS repoids enablement is expected. 28 | 4/ The start date of the EUS phase is set far to the past to simulate the EUS phase began. 29 | The --eus option *is used*. 30 | The report is expected to print out a WARNING and advise to use the --eus option. 31 | tag+: 32 | - test-eus-enablement 33 | test: | 34 | pytest -m test_eus_enablement 35 | 36 | /non_eus_account: 37 | description: | 38 | Verify that Convert2RHEL is working properly when EUS repositories are not available for conversions 39 | to RHEL EUS minor versions (8.6, ...) and the --eus option is provided. The regular repositories 40 | should be enabled. 41 | tag+: 42 | - test-rhsm-non-eus-account 43 | - non-sca 44 | test: | 45 | pytest -m test_rhsm_non_eus_account 46 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/file-backup/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Handling file backup and restore 3 | 4 | description+: | 5 | This test verifies correct handling of backup and restore of config files. 6 | "/etc/cloud/cloud.cfg", "/etc/NetworkManager/NetworkManager.conf", 7 | "/etc/logrotate.d/yum" and "/etc/logrotate.d/dnf" are in scope of this test. 8 | The following scenarios are verified: 9 | 1/ The config files are modified with additional data 10 | The contents are compared pre- and post-conversion analysis task 11 | and should remain the same. 12 | 2/ The config files are removed pre-conversion analysis task 13 | and should remain absent post-rollback. 14 | Additionally, validates that a file clash does not happen during a backup. 15 | There was a clash happening in the way convert2rhel backups files, 16 | if there is a file to back up that has the same name as one directory 17 | or another file already created, an error will be thrown to the user. 18 | For that scenario we utilize "/etc/logrotate.d/yum" 19 | and "/etc/logrotate.d/yum" files. 20 | 21 | tag+: 22 | - file-backup 23 | - sanity 24 | 25 | test: | 26 | pytest -m test_file_backup 27 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/firewalld-inhibitor/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Running firewalld inhibitor 3 | description: | 4 | Verify that on the OL8.8 the conversion is inhibited when 5 | the firewalld is running on the system and the `CleanupModulesOnExit` 6 | configuration option is set to `yes` in firewalld configuration file. 7 | This only applies to Oracle Linux (>=) 8.8. 8 | 9 | enabled: false 10 | adjust+: 11 | - enabled: true 12 | when: distro == oracle-8-latest 13 | because: The test case applies to Oracle Linux 8.8 14 | 15 | /firewalld_inhibitor: 16 | tag+: 17 | - firewalld-inhibitor 18 | test: | 19 | pytest -m test_firewalld_inhibitor 20 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/firewalld-inhibitor/test_firewalld_inhibitor.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pytest 4 | 5 | from conftest import TEST_VARS 6 | 7 | 8 | FIREWALLD_CONFIG_FILE = "/etc/firewalld/firewalld.conf" 9 | 10 | 11 | def test_firewalld_inhibitor(shell, convert2rhel): 12 | """ 13 | Verify that on the OL8.8 the conversion is inhibited when 14 | the firewalld is running on the system and the `CleanupModulesOnExit` 15 | configuration option is set to `yes` in firewalld configuration file. 16 | The reference ticket: https://issues.redhat.com/browse/RHELC-1180 17 | """ 18 | if not os.path.exists(FIREWALLD_CONFIG_FILE): 19 | pytest.fail("Firewalld configuration file does not exist") 20 | 21 | shell(f"sed -i 's/CleanupModulesOnExit=no/CleanupModulesOnExit=yes/g' {FIREWALLD_CONFIG_FILE}") 22 | 23 | shell("firewall-cmd --reload") 24 | assert shell("systemctl status firewalld").returncode == 0 25 | 26 | with convert2rhel( 27 | "-y --debug --serverurl {} --username {} --password {}".format( 28 | TEST_VARS["RHSM_SERVER_URL"], TEST_VARS["RHSM_SCA_USERNAME"], TEST_VARS["RHSM_SCA_PASSWORD"] 29 | ), 30 | unregister=True, 31 | ) as c2r: 32 | c2r.expect("Pre-conversion analysis report") 33 | c2r.expect( 34 | "CHECK_FIREWALLD_AVAILABILITY::FIREWALLD_MODULES_CLEANUP_ON_EXIT_CONFIG", 35 | timeout=600, 36 | ) 37 | 38 | assert c2r.exitstatus == 2 39 | 40 | shell(f"sed -i 's/CleanupModulesOnExit=yes/CleanupModulesOnExit=no/g' {FIREWALLD_CONFIG_FILE}") 41 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/grub/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Change the grub file 3 | 4 | description: | 5 | Modify the /etc/default/grub file and verify correct output and successful conversion. 6 | 7 | tag+: 8 | - sanity 9 | - grub 10 | - grub-mkfile 11 | 12 | /invalid_changes_to_grub_file: 13 | summary+: | 14 | Introduce invalid changes 15 | description+: | 16 | Invalid changes, e.g. removing the `=` should cause the 'grub2-mkfile' call to fail. 17 | Verify that an error is raised in such scenario. 18 | tag+: 19 | - grub-change-invalid 20 | test: pytest -m test_invalid_changes_to_grub_file 21 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/grub/test_invalid_changed_to_grub.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import fileinput 4 | import os.path 5 | 6 | import pytest 7 | 8 | from conftest import TEST_VARS 9 | 10 | 11 | target_line = "GRUB_CMDLINE_LINUX" 12 | 13 | 14 | @pytest.fixture 15 | def grub_file_invalid(shell, backup_directory): 16 | """ 17 | Modify the /etc/default/grub file with 'invalid' changes. 18 | These changes should cause the 'grub2-mkfile' call to fail. 19 | The changes made to the grub file result into: 20 | 5 GRUB_TERMINAL_OUTPUT="foo" 21 | 6 GRUB_CMDLINE_LINUX 22 | 7 GRUB_DISABLE_RECOVERY="bar" 23 | """ 24 | grub_config = "/etc/default/grub" 25 | grub_config_bkp = os.path.join(backup_directory, "grub.bkp") 26 | 27 | # Backup the original file 28 | shell(f"cp {grub_config} {grub_config_bkp}") 29 | 30 | # Make invalid changes to the grub file 31 | for line in fileinput.FileInput(grub_config, inplace=True): 32 | if target_line in line: 33 | line = line.replace(line, target_line + "\n") 34 | print(line, end="") 35 | 36 | yield 37 | 38 | # Restore from backup 39 | shell(f"mv -f {grub_config_bkp} {grub_config}") 40 | 41 | 42 | def test_invalid_changes_to_grub_file(convert2rhel, grub_file_invalid): 43 | """ 44 | Validate that an error is raised, when the grub config file contains invalid values. 45 | """ 46 | 47 | with convert2rhel( 48 | "analyze -y --serverurl {} --username {} --password {} --debug".format( 49 | TEST_VARS["RHSM_SERVER_URL"], 50 | TEST_VARS["RHSM_SCA_USERNAME"], 51 | TEST_VARS["RHSM_SCA_PASSWORD"], 52 | ) 53 | ) as c2r: 54 | assert c2r.expect_exact("Prepare: Check if the grub file is valid") == 0 55 | assert ( 56 | c2r.expect_exact("ERROR - (ERROR) GRUB_VALIDITY::INVALID_GRUB_FILE - Grub boot entry file is invalid") == 0 57 | ) 58 | 59 | assert c2r.exitstatus == 2 60 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/kernel-modules/files/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += my_kmod.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=/tmp/my-test/ modules 5 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/kernel-modules/files/my_kmod.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | MODULE_LICENSE("Proprietary"); 6 | //MODULE_LICENSE("GPL"); 7 | MODULE_AUTHOR("Martin Litwora"); 8 | MODULE_DESCRIPTION("Module for testing purpose, prints 'Hello world!'"); 9 | 10 | static int __init hello_init(void) 11 | { 12 | printk(KERN_INFO "Hello world!\n"); 13 | return 0; 14 | } 15 | 16 | static void __exit hello_cleanup(void) 17 | { 18 | printk(KERN_INFO "Cleaning up module.\n"); 19 | } 20 | 21 | module_init(hello_init); 22 | module_exit(hello_cleanup); 23 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/kernel/files/broken_repo.repo: -------------------------------------------------------------------------------- 1 | [broken_repo] 2 | name=Broken repository for verification test purposes 3 | baseurl=http://download.eng.bos.redhat.com/beakerrepos/client/Fedor36/ 4 | enabled=1 5 | gpgcheck=0 6 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/logged-command/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Passed command at the top of a log file 3 | description: | 4 | Verify log file is generated and the passed command is in first lines of the log file. 5 | 6 | tier: 0 7 | 8 | tag+: 9 | - logged-command 10 | 11 | /logfile_starts_with_command: 12 | tag+: 13 | - logfile-starts-with-command 14 | - sanity 15 | test: | 16 | pytest -m test_logfile_starts_with_command 17 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Set of non-destructive tests 3 | 4 | description+: | 5 | All tests are non-destructive, meaning there is not a full conversion being done. 6 | The latest point of verification for these tests is PONR (point of no return). 7 | The preparation and cleanup phase is implemented in the test itself. 8 | 9 | tag+: 10 | - non-destructive 11 | 12 | environment+: 13 | C2R_TESTS_NONDESTRUCTIVE: 1 14 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/modified-releasever/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Modified `releasever` variable 3 | description: | 4 | Modify the releasever in multiple scenarios and verify the expected behavior. 5 | 6 | tier: 0 7 | 8 | tag+: 9 | - modified-releasever 10 | 11 | /modified_releasever_in_configs: 12 | summary+: | 13 | Modified releasever in convert2rhel configs 14 | description+: | 15 | Verify that modifying the releasever value in config files 16 | at `/usr/share/convert2rhel/configs/` will override the system 17 | $releasever when calling the `yumdownloader` command. 18 | tag+: 19 | - modified-releasever-in-configs 20 | test: | 21 | pytest -m test_releasever_modified_in_c2r_config 22 | 23 | /modified_releasever_to_unknown_release: 24 | summary+: | 25 | Set /etc/system-release to unsupported version 26 | description+: | 27 | Verify that running not allowed OS release inhibits the conversion. 28 | Modify the /etc/system-release file to set the releasever to an unsupported version (e.g. x.1.1111) 29 | tag+: 30 | - releasever-unknown-release 31 | - inhibitor 32 | test: | 33 | pytest -m test_inhibitor_releasever_noexistent_release 34 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/problematic-third-party-pkgs/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Problematic 3rd party packages listed 3 | description+: | 4 | Verify that the overridable checks work as intended in both 5 | scenarios with or without the respective envar set. 6 | 7 | /list_third_party_pkgs: 8 | summary+: | 9 | List third party packages check 10 | description+: | 11 | This test verifies, that the TASK - [Prepare: List third-party packages] 12 | won't fail listing packages if previously problematic third party packages are installed. 13 | Installed package(s): 14 | v8-devel from the epel repository 15 | nodejs from the epel repository 16 | tag+: 17 | - test-list-third-party-pkgs 18 | test: | 19 | pytest -m test_list_third_party_pkgs 20 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/problematic-third-party-pkgs/test_problematic_third_party_pkgs.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from conftest import TEST_VARS 4 | 5 | 6 | @pytest.fixture 7 | def problematic_third_party_package(shell): 8 | """ 9 | Install problematic package which previously caused the TASK - [Prepare: List third-party packages] 10 | to fail. 11 | Installed package(s): 12 | v8-devel from the epel repository 13 | nodejs from the epel repository 14 | """ 15 | problematic_pkg_and_repo = {"v8-devel": "epel", "nodejs": "epel"} 16 | package_installed = [] 17 | 18 | for pkg, repo in problematic_pkg_and_repo.items(): 19 | if shell(f"rpm -q {pkg}").returncode == 1: 20 | shell(f"yum install -y {pkg} --enablerepo={repo}") 21 | package_installed.append(pkg) 22 | 23 | yield 24 | 25 | for pkg in package_installed: 26 | shell(f"yum remove -y {pkg}") 27 | 28 | 29 | def test_list_third_party_pkgs(convert2rhel, problematic_third_party_package): 30 | """ 31 | This test verifies, that the TASK - [Prepare: List third-party packages] 32 | won't fail listing packages if previously problematic third party packages are installed. 33 | Installed package(s): 34 | v8-devel from the epel repository 35 | nodejs from the epel repository 36 | """ 37 | with convert2rhel( 38 | "analyze -y --serverurl {} --username {} --password {} --debug".format( 39 | TEST_VARS["RHSM_SERVER_URL"], 40 | TEST_VARS["RHSM_SCA_USERNAME"], 41 | TEST_VARS["RHSM_SCA_PASSWORD"], 42 | ) 43 | ) as c2r: 44 | # Verify that the analysis report is printed 45 | c2r.expect("Pre-conversion analysis report", timeout=600) 46 | 47 | # The analysis should exit with 0, if it finishes successfully 48 | assert c2r.exitstatus == 0 49 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/rhsm-facts/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | RHSM facts update when in analysis mode 3 | description+: | 4 | Verify that the subscription-manager facts command is called after the 5 | analysis is done (either succeeding or failing). 6 | 7 | /rhsm_facts_update_called_after_analysis: 8 | summary+: | 9 | RHSM facts update after analysis 10 | description+: | 11 | This test verifies that the RHSM facts are uploaded when running 12 | convert2rhel with analysis option. 13 | tag+: 14 | - test-rhsm-facts-called-in-analysis 15 | test: | 16 | pytest -m test_rhsm_facts_update_called_after_analysis 17 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/rhsm-facts/test_rhsm_facts_update_analysis.py: -------------------------------------------------------------------------------- 1 | def test_rhsm_facts_update_called_after_analysis(convert2rhel, pre_registered): 2 | """ 3 | Verify that the RHSM custom facts are uploaded after the analysis is done. 4 | """ 5 | with convert2rhel("analyze -y --debug") as c2r: 6 | # Verify that the analysis report is printed 7 | c2r.expect("Updating RHSM custom facts collected during the conversion.", timeout=600) 8 | c2r.expect("RHSM custom facts uploaded successfully.", timeout=600) 9 | 10 | # The analysis should exit with 0, if it finishes successfully 11 | assert c2r.exitstatus == 0 12 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/subscription-manager/test_sub_man_rollback.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_sub_man_rollback(convert2rhel, shell, fixture_subman): 5 | """ 6 | Verify that convert2rhel removes and backs up the original vendor subscription-manager packages, including 7 | python3-syspurpose and python3-cloud-what which are also built out of the subscription-manager SRPM. 8 | 9 | Not removing and backing up the python3-syspurpose and python3-cloud-what packages on CentOS Linux 8.5 was causing 10 | a rollback failure when an older version of these two packages was installed. 11 | 12 | When a reinstallation of removed packages failed during the rollback due to not having the right versions of updated 13 | dependencies backed up, the system was left without the centos-linux-release package installed, leading to the 14 | $releasever variable being undefined, and ultimately causing a traceback during a subsequent execution of 15 | convert2rhel (https://issues.redhat.com/browse/RHELC-762). 16 | """ 17 | # By running convert2rhel twice we make sure that the rollback of the first run 18 | # correctly reinstalled centos-linux-release and subscription-manager* and the second run then does not fail 19 | # due to not being able to expand the $releasever variable 20 | for run in range(2): 21 | with convert2rhel( 22 | "-y --serverurl {} --username {} --password {} --debug".format( 23 | TEST_VARS["RHSM_SERVER_URL"], 24 | TEST_VARS["RHSM_SCA_USERNAME"], 25 | TEST_VARS["RHSM_SCA_PASSWORD"], 26 | ) 27 | ) as c2r: 28 | assert c2r.expect("Validate the dnf transaction") == 0 29 | # At this point the centos-linux-release package is already installed 30 | c2r.sendcontrol("c") 31 | # Expect rollback, otherwise TIMEOUT 32 | c2r.expect("WARNING - Abnormal exit! Performing rollback", timeout=10) 33 | 34 | assert c2r.exitstatus == 1 35 | 36 | assert shell("rpm -q subscription-manager").returncode == 0 37 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/system-release-backup/files/baseos.repo: -------------------------------------------------------------------------------- 1 | [baseos] 2 | name=CentOS Linux 8 BaseOS 3 | baseurl=https://vault.centos.org/centos/8/BaseOS/x86_64/os/ 4 | gpgcheck=0 5 | enabled=1 6 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/system-release-backup/files/ubi.repo: -------------------------------------------------------------------------------- 1 | [ubi] 2 | name=Universal Base Image 7 3 | baseurl=https://cdn-ubi.redhat.com/content/public/ubi/dist/ubi/server/7/7Server/x86_64/os/ 4 | gpgcheck=0 5 | enabled=1 6 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/user-prompt-response/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | User response is empty 3 | 4 | tier: 0 5 | 6 | tag+: 7 | - user-prompt-response 8 | 9 | /empty_user_response_username_and_password: 10 | # The test is disabled because there are no interactive prompts for the user when the 11 | # credentials are missing and the machine is not registered before. 12 | # When the prompts for the user are put back we can re-enable the test. 13 | enabled: false 14 | summary+: | 15 | Pass an empty string for username and password 16 | description+: | 17 | Verify that the user is enforced to input a value and passing an empty string 18 | loops back to the user prompt. 19 | Verify for both username and password. 20 | The functionality is generic enough, so there is no need to verify other prompts. 21 | tag+: 22 | - empty-username-and-password 23 | test: | 24 | pytest -m test_empty_user_response_username_and_password 25 | -------------------------------------------------------------------------------- /tests/integration/tier0/non-destructive/user-prompt-response/test_user_prompt_response.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_empty_user_response_username_and_password(convert2rhel): 5 | """ 6 | Run c2r registration with no username and password provided. 7 | Verify that user has to pass non-empty username/password string to continue, otherwise enforce the input prompt again. 8 | """ 9 | with convert2rhel("-y --serverurl {}".format(TEST_VARS["RHSM_SERVER_URL"]), unregister=True) as c2r: 10 | c2r.expect(" ... activation key not found, username and password required") 11 | c2r.expect("Username") 12 | c2r.sendline() 13 | # Assert the prompt loops and returns "Username:" 14 | # when the input is empty, hence the '0' index. 15 | # In case the loop doesn't work, the prompt returns 16 | # "Password" and raises the assertion error. 17 | assert c2r.expect("Username", timeout=300) == 0 18 | # Provide username, expect password prompt 19 | 20 | retries = 0 21 | while True: 22 | c2r.sendline(TEST_VARS["RHSM_SCA_USERNAME"]) 23 | c2r.expect("Password: ") 24 | c2r.sendline() 25 | try: 26 | assert c2r.expect("Password", timeout=300) == 0 27 | # Provide password, expect successful registration and subscription prompt 28 | c2r.sendline(TEST_VARS["RHSM_SCA_PASSWORD"]) 29 | assert c2r.expect("System registration succeeded", timeout=180) == 0 30 | break 31 | except Exception: 32 | retries = retries + 1 33 | if retries == 3: 34 | raise 35 | continue 36 | 37 | c2r.sendcontrol("c") 38 | assert c2r.exitstatus == 1 39 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/changed-grub-file/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Change the grub file 3 | 4 | description: | 5 | Modify the /etc/default/grub file and verify correct output and successful conversion. 6 | 7 | tag+: 8 | - grub 9 | - grub-mkfile 10 | 11 | 12 | /valid_changes_to_grub_file: 13 | summary+: | 14 | Introduce valid changes 15 | description+: | 16 | Valid changes are represented by adding newlines, whitespaces and comments. 17 | Verify a successful conversion. 18 | tag+: 19 | - grub-change-valid 20 | test: pytest -m test_valid_changes_to_grub_file 21 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/changed-grub-file/test_valid_changed_grub.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import fileinput 4 | 5 | from conftest import TEST_VARS 6 | 7 | 8 | target_line = "GRUB_CMDLINE_LINUX" 9 | 10 | 11 | def test_valid_changes_to_grub_file(convert2rhel): 12 | """ 13 | Modify the /etc/default/grub file with 'valid' changes adding newlines, whitespaces and comments. 14 | Valid meaning that none of the changes should cause any issue calling 'grub2-mkconfig'. 15 | The changes made to the grub file result into: 16 | 5 GRUB_TERMINAL_OUTPUT="foo" 17 | 6 18 | 7 # comment added by test 19 | 8 GRUB_CMDLINE_LINUX="bar" # comment added by test 20 | 9 # comment added by test 21 | 10 22 | 11 GRUB_DISABLE_RECOVERY="foobar" 23 | """ 24 | block_comment = "\n# comment added by test\n" 25 | inline_comment_post = "# comment added by test" 26 | whitespace = " " 27 | for line in fileinput.FileInput("/etc/default/grub", inplace=True): 28 | if target_line in line: 29 | line = line.replace("\n", "") 30 | line = line.replace( 31 | line, 32 | block_comment + whitespace + line + whitespace + inline_comment_post + block_comment + "\n", 33 | ) 34 | print(line, end="") 35 | 36 | with convert2rhel( 37 | "-y --serverurl {} --username {} --password {} --debug".format( 38 | TEST_VARS["RHSM_SERVER_URL"], 39 | TEST_VARS["RHSM_SCA_USERNAME"], 40 | TEST_VARS["RHSM_SCA_PASSWORD"], 41 | ) 42 | ) as c2r: 43 | assert c2r.expect("Successfully updated GRUB2 on the system.") == 0 44 | assert c2r.exitstatus == 0 45 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/changed-yum-conf/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Change yum configuration file 3 | 4 | description: | 5 | Test a scenario in which the user modifies /etc/yum.conf 6 | before the conversion. In that case, the config file does not get replaced 7 | during the conversion with the config file from the RHEL package. 8 | Make sure that C2R patches the config file 9 | and verify that the yum works after a successful conversion. 10 | 11 | link: 12 | - verifies: https://issues.redhat.com/browse/RHELC-365 13 | 14 | /yum_conf_patch: 15 | tag+: 16 | - yum 17 | - yum-patch 18 | 19 | test: pytest -m test_yum_conf_patch 20 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/changed-yum-conf/test_patch_yum_conf.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS, SystemInformationRelease 2 | 3 | 4 | def test_yum_conf_patch(convert2rhel, shell): 5 | """Test the scenario in which the user modifies /etc/yum.conf before the conversion. 6 | In that case during the conversion the config file does not get replaced with the config file from the RHEL package 7 | (%config(noreplace)) and we need to make sure that we patch the config file to get rid of the distroverpkg config 8 | key. Leaving the distroverpkg key there would lead to errors when calling yum after the conversion for not 9 | expanding the $releasever variable properly. 10 | """ 11 | shell("echo '#random text' >> /etc/yum.conf") 12 | pkgmanager_conf = "/etc/yum.conf" 13 | if SystemInformationRelease.version.major >= 8: 14 | pkgmanager_conf = "/etc/dnf/dnf.conf" 15 | 16 | with convert2rhel( 17 | "-y --serverurl {} --username {} --password {} --debug".format( 18 | TEST_VARS["RHSM_SERVER_URL"], 19 | TEST_VARS["RHSM_SCA_USERNAME"], 20 | TEST_VARS["RHSM_SCA_PASSWORD"], 21 | ) 22 | ) as c2r: 23 | c2r.expect("{} patched.".format(pkgmanager_conf)) 24 | assert c2r.exitstatus == 0 25 | 26 | # The tsflags will prevent updating the RHEL-8.5 versions to RHEL-8.6 27 | assert shell("yum update -y -x convert2rhel --setopt tsflags=test").returncode == 0 28 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/detect-bootloader-partition/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Detect correct bootloader partition 3 | 4 | description: | 5 | Verify that Convert2RHEL detected the correct boot partition. 6 | This test is supposed to be ran exclusively on UEFI machines. 7 | 8 | tag+: 9 | - uefi 10 | - bootloader 11 | 12 | link: 13 | - verifies: https://issues.redhat.com/browse/RHELC-733 14 | 15 | /detect_correct_boot_partition: 16 | test: pytest -m test_detect_correct_boot_partition 17 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/error-after-ponr/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Trigger a error after PONR 3 | description: | 4 | Verify that convert2rhel exits with 2 after a error in PONR 5 | Verify that the error is logged with a message to the user 6 | This test will break the machine, there is no reboot or checks after this test 7 | 8 | /error_after_ponr: 9 | test: pytest -m test_error_after_ponr 10 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/error-after-ponr/test_error_after_ponr.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_error_after_ponr(convert2rhel, shell): 5 | """ 6 | Verify the improved explanatory log message is displayed to the user when a fail occurs 7 | after the point of no return. Also verify that the exit code is 2. 8 | 9 | This test destroys the machine so neither reboot nor any checks after conversion are called 10 | """ 11 | assert shell("yum install dnsmasq -y").returncode == 0 12 | with convert2rhel( 13 | "-y --serverurl {} --username {} --password {} --debug".format( 14 | TEST_VARS["RHSM_SERVER_URL"], 15 | TEST_VARS["RHSM_SCA_USERNAME"], 16 | TEST_VARS["RHSM_SCA_PASSWORD"], 17 | ) 18 | ) as c2r: 19 | # Wait until Point of no return appears. Then block all the internet connection 20 | c2r.expect_exact("WARNING - The tool allows rollback of any action until this point.") 21 | c2r.expect_exact("Convert: Replace system packages") 22 | 23 | # Everything is resolved to localhost 24 | with open("/etc/dnsmasq.conf", "a") as f: 25 | f.write("address=/#/127.0.0.1") 26 | 27 | with open("/etc/resolv.conf", "w") as f: 28 | f.write("nameserver 127.0.0.1") 29 | 30 | assert shell("systemctl enable dnsmasq && systemctl restart dnsmasq").returncode == 0 31 | 32 | c2r.expect("WARNING - The conversion process failed") 33 | c2r.expect( 34 | "The system is left in an undetermined state that Convert2RHEL cannot fix. The system might not be fully converted, and might incorrectly be reporting as a Red Hat Enterprise Linux machine" 35 | ) 36 | c2r.expect( 37 | "It is strongly recommended to store the Convert2RHEL logs for later investigation, and restore the system from a backup" 38 | ) 39 | 40 | assert c2r.exitstatus == 2 41 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/excluded-packages-removed/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Excluded packages removed 3 | description: | 4 | Verify, that convert2rhel removes packages, which are specified as excluded_pkgs in config. 5 | Verification scenarios cover just some of the packages causing the most issues. 6 | Those are specified in their respective test plan (remove_excluded_pkgs_epel7 and remove_excluded_pkgs_epel8). 7 | Packages are passed to the test as an environment variable through their respective plan. 8 | 9 | 10 | tag+: 11 | - excluded-packages 12 | 13 | /excluded_packages_removed: 14 | test: pytest -m test_excluded_packages_removed 15 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/excluded-packages-removed/test_excluded_pkgs_removed.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from conftest import TEST_VARS 4 | 5 | 6 | def test_excluded_packages_removed(shell, convert2rhel): 7 | """ 8 | Verify, that convert2rhel removes packages, which are specified as excluded_pkgs in config. 9 | Verification scenarios cover just some of the packages causing the most issues. 10 | Those are specified in their respective test plan (remove_excluded_pkgs_epel7 and remove_excluded_pkgs_epel8). 11 | Packages are set as an environment variable. 12 | """ 13 | packages = os.environ["PACKAGES"] 14 | assert ( 15 | shell( 16 | f"yum install -y {packages}", 17 | ).returncode 18 | == 0 19 | ) 20 | 21 | # run utility until the reboot 22 | with convert2rhel( 23 | "-y --serverurl {} --username {} --password {} --debug".format( 24 | TEST_VARS["RHSM_SERVER_URL"], 25 | TEST_VARS["RHSM_SCA_USERNAME"], 26 | TEST_VARS["RHSM_SCA_PASSWORD"], 27 | ) 28 | ) as c2r: 29 | pass 30 | assert c2r.exitstatus == 0 31 | 32 | # Verify, the excluded packages were really removed 33 | # RPM return code depends on the number of packages that are not installed. 34 | # If the query contains 3 packages and none of them is installed then the 35 | # return code is 3. 36 | assert shell(f"rpm -qi {packages}").returncode == len(packages.split(" ")) 37 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/firewalld-disabled-ol8/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | firewalld disabled before the conversion 3 | description: | 4 | Verify that on the OL8.8 the conversion does not break when 5 | firewalld is not running and the the `CleanupModulesOnExit` configuration 6 | option is set to `yes` in firewalld configuration file (default value). 7 | This only applies to Oracle Linux (>=) 8.8. 8 | 9 | tag+: 10 | - firewalld-disabled 11 | 12 | test: | 13 | pytest -m test_firewalld_disabled_ol8 14 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/firewalld-disabled-ol8/test_firewalld_disabled_ol8.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pytest 4 | 5 | from conftest import TEST_VARS 6 | 7 | 8 | FIREWALLD_CONFIG_FILE = "/etc/firewalld/firewalld.conf" 9 | 10 | 11 | def test_firewalld_disabled_ol8(shell, convert2rhel): 12 | """ 13 | Verify that when the firewalld is not running and the configuration option has 14 | default value, the conversion can proceed without problems on Oracle-Linux 8.8. 15 | The reference ticket: https://issues.redhat.com/browse/RHELC-1180 16 | """ 17 | if not os.path.exists(FIREWALLD_CONFIG_FILE): 18 | pytest.fail("Firewalld configuration file does not exist") 19 | 20 | assert shell("systemctl stop firewalld").returncode == 0 21 | assert shell("systemctl disable firewalld").returncode == 0 22 | 23 | shell(f"sed -i 's/CleanupModulesOnExit=no/CleanupModulesOnExit=yes/g' {FIREWALLD_CONFIG_FILE}") 24 | 25 | with convert2rhel( 26 | "-y --debug --serverurl {} --username {} --password {}".format( 27 | TEST_VARS["RHSM_SERVER_URL"], TEST_VARS["RHSM_SCA_USERNAME"], TEST_VARS["RHSM_SCA_PASSWORD"] 28 | ), 29 | ) as c2r: 30 | c2r.expect("Firewalld service reported that it is not running.") 31 | 32 | assert c2r.exitstatus == 0 33 | 34 | # There should not be any problems 35 | assert shell("grep -i 'traceback' /var/log/convert2rhel/convert2rhel.log").returncode == 1 36 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/host-metering/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Check expected state after configuring host metering 3 | 4 | description+: | 5 | Test convert2rhel with CONVERT2RHEL_CONFIGURE_HOST_METERING env var. 6 | Verify that: 7 | - host-metering service is enabled and started 8 | 9 | link: 10 | - https://issues.redhat.com/browse/RHELC-1226 11 | 12 | /test_host_metering_conversion: 13 | tag+: 14 | - test-host-metering-conversion 15 | test: pytest -m test_run_conversion_with_host_metering 16 | 17 | /check_active_host_metering: 18 | tag+: 19 | - check-active-host-metering 20 | test: pytest -m test_active_host_metering 21 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/host-metering/test_host_metering_enabled.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright(C) 2024 Red Hat, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | 19 | def test_active_host_metering(shell): 20 | """ 21 | Verify that host-metering is enabled and started after conversion on 22 | a hyperscaler. 23 | """ 24 | # Verify that host-metering is enabled and started 25 | assert shell("systemctl is-enabled host-metering.service").returncode == 0 26 | assert shell("systemctl is-active host-metering.service").returncode == 0 27 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/kernel-boot-files/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Handle kernel boot files issues 3 | 4 | description: | 5 | Verify that Convert2RHEL can detect and handle the kernel boot files in 6 | case of failure. 7 | Verify that, if present, the kernel boot files are not corrupted. 8 | 9 | In any case, the conversion should not be inhibited. A warning will be 10 | shown to the user with instructions on how to fix it. 11 | 12 | tag+: 13 | - kernel 14 | - boot 15 | - initramfs 16 | 17 | /corrupted_initramfs_file: 18 | summary+: | 19 | Corrupted initramfs file 20 | description+: | 21 | Verify, that a warning message is printed out to the user in case of a corrupted initramfs file. 22 | This case can happen when the transaction is run successfully, due to the lack of 23 | a disk space in the /boot partition, the kernel scriptlet will fail to copy 24 | the uncompressed initramfs file to /boot/initramfs-*.img, thus, leaving the 25 | file in a partial state and corrupted. 26 | test: pytest -m test_handling_corrupted_initramfs_file 27 | 28 | /missing_kernel_boot_files: 29 | summary+: | 30 | Missing kernel boot files in /boot 31 | description+: | 32 | Verify, that a warning message is printed out to the user in case 33 | the tool can't detect the initramfs and vmlinuz files in /boot. 34 | This case can happen if the kernel scriptlet fails during the yum/dnf 35 | transaction where Convert2RHEL tries to replace the packages. Even though 36 | the scriptlet can fail, the transaction will still continue and the 37 | workflow will continue to be executed. The problem is that, with a 38 | scriptlet failure when replacing/installing a kernel, the initramfs and 39 | vmlinuz may not be available in the /boot partition, especially if there 40 | isn't sufficient disk space available in there. This test has the intention 41 | to verify that the warning with the correct steps are provided to the 42 | user in order to overcome this case and fix it for them. 43 | test: pytest -m test_handling_missing_kernel_boot_files 44 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/kernel-check-skip/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Skip latest kernel check with older kernel 3 | 4 | description+: | 5 | Verify that it's possible to run the full conversion with older kernel, 6 | than available in the RHEL repositories. 7 | 1/ Install older kernel on the system 8 | 2/ Make sure the `CONVERT2RHEL_SKIP_KERNEL_CURRENCY_CHECK` is in place 9 | * doing that we also verify, the deprecated envar is still allowed 10 | 3/ Enable *just* the rhel-7-server-rpms repository 11 | 4/ Run conversion verifying the conversion is not inhibited and completes successfully 12 | 13 | tag+: 14 | - kernel 15 | 16 | /latest_kernel_check_skip: 17 | test: pytest -m test_latest_kernel_check_skip 18 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/kernel-core-only/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Only kernel-core package installed 3 | 4 | description: | 5 | This tests sets up the machine that it contains only the `kernel-core` package installed 6 | on the system. Test is only viable to run on RHEL-8 like systems. 7 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/kernel-core-only/remove_kernel_pkg.py: -------------------------------------------------------------------------------- 1 | def test_remove_kernel_pkg(shell): 2 | """ 3 | This tests set's up the machine that it contains only kernel-core package on the system. 4 | Test is only viable to run on RHEL-8 like systems. 5 | """ 6 | 7 | assert shell("yum install kernel-core -y").returncode == 0 8 | 9 | assert shell("yum remove kernel -y -x kernel-core").returncode == 0 10 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Destructive plans 3 | 4 | description+: | 5 | Set of destructive plans performing full conversion. 6 | Plan usually consist of a preparation phase preparing the system for the main test run. 7 | The reboot is performed by using tmt-reboot function with help of TMT_REBOOT_COUNT environment variable. 8 | After rebooting to RHEL a set of after conversion checks is run. 9 | For some plans there might be some checks excluded. 10 | 11 | tag+: 12 | - destructive 13 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/multiple-nic/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Conversion with multiple NICs 3 | 4 | description+: | 5 | Verify, that it's possible to do a full conversion of the system 6 | that has more than one NIC connected and running. 7 | The test uses RHSM as a conversion method. 8 | 9 | test: | 10 | pytest -m test_provisioned_machine 11 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/multiple-nic/multiple_nic.py: -------------------------------------------------------------------------------- 1 | def test_provisioned_machine(shell): 2 | assert shell("ip link show").returncode == 0 3 | # Make sure we have at least 2 non-loopback NICs 4 | non_loopback_nics = shell("ip -br link show | grep -v LOOPBACK | wc -l") 5 | assert int(non_loopback_nics.output.strip()) >= 2 6 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/one-kernel-scenario/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | One kernel scenario 3 | 4 | description: | 5 | Test the edge-case scenario where the installed 6 | kernel is the same version as the one in enabled RHEL repositories. 7 | The RHEL repositories contain only this one kernel. The test verifies 8 | that C2R is able to replace the installed kernel with the RHEL one correctly. 9 | 10 | #TODO https://issues.redhat.com/browse/RHELC-922 11 | 12 | link: 13 | - verifies: https://issues.redhat.com/browse/RHELC-37 14 | 15 | tag+: 16 | - one-kernel-scenario 17 | - kernel 18 | 19 | enabled: false 20 | adjust+: 21 | - enabled: true 22 | when: > 23 | distro == centos-7, oracle-7 24 | 25 | /one_kernel_scenario: 26 | test: pytest -m test_one_kernel_scenario 27 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/os-release-removal/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Remove /etc/os-release 3 | 4 | description: | 5 | Remove /etc/os-release file and verify, that the conversion is successful. 6 | NOTE: Using the Satellite method for registration would result in registration failure. 7 | 8 | tag+: 9 | - sysrelease 10 | - os-release 11 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/os-release-removal/remove_os_release.py: -------------------------------------------------------------------------------- 1 | def test_missing_os_release(shell): 2 | """ 3 | This test preparation is used to verify that it's possible 4 | to do full conversion when /etc/os-release file is not present on the system. 5 | The reference PR: https://github.com/oamg/convert2rhel/pull/384 6 | 7 | Note that using the satellite as a method of conversion is not 8 | supported at the moment and will fail during the registration process. 9 | """ 10 | assert shell("rm /etc/os-release").returncode == 0 11 | assert shell("find /etc/os-release").returncode == 1 12 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/proxy-conversion/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Conversion using a proxy server 3 | 4 | description+: | 5 | Restrict the system internet connection only to a forward proxy server. 6 | This is done by setting up a firewall setting on the machine. 7 | Also for conversion to work it is necessary to enabled connection to specific 8 | URLs directly from the machine. 9 | Verify that the conversion is successful. 10 | tag+: 11 | - proxy-conversion 12 | 13 | /proxy_conversion: 14 | test: pytest -svv -m test_proxy_conversion 15 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/set-locale/use_non_english_language.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from conftest import SYSTEM_RELEASE_ENV, SystemInformationRelease 4 | 5 | 6 | def test_use_non_english_language(shell): 7 | """ 8 | We need to test the ability of convert2rhel to convert the system when non english 9 | language is set (using non ascii language). 10 | Ref bug: https://bugzilla.redhat.com/show_bug.cgi?id=2022854 11 | """ 12 | # install Chinese language pack for CentOS-8 and Oracle Linux 8 13 | 14 | if re.match(r"^(centos|oracle|alma|rocky)-[89]", SYSTEM_RELEASE_ENV): 15 | assert shell("dnf install glibc-langpack-zh -y").returncode == 0 16 | 17 | # set locale variables that affect translations to Chinese 18 | utf8 = "UTF-8" if SystemInformationRelease.version.major == 9 else "utf8" 19 | assert shell(f"localectl list-locales | grep zh_CN.{utf8}").returncode == 0 20 | assert shell(f"localectl set-locale LANG=zh_CN.{utf8} LC_MESSAGES=zh_CN.{utf8} LANGUAGE=zh_CN").returncode == 0 21 | 22 | # Testing farm is returning an error on CentOS7 mentioning 23 | # setting incompatible LC_CTYPE C.UTF-8. 24 | # However, the C.UTF-8 was added on RHEL-8 like distros. 25 | if "centos-7" in SYSTEM_RELEASE_ENV: 26 | assert shell("localectl set-locale LC_CTYPE=zh_CN.utf8").returncode == 0 27 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/system-not-up-to-date/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | System not updated 3 | description: | 4 | Verify that the conversion emits a warning if there are packages which are not updated to the latest. 5 | Verify that the conversion emits a warning if the yum versionlock plugin is being used. 6 | Verify the conversion succeeds anyway. 7 | 8 | /system_not_updated: 9 | test: pytest -m test_system_not_updated 10 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/unavailable-package/ansible/install_pkg_removed_from_centos_85_repos.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | tasks: 3 | - name: Add Centos 8.4.2105 BaseOS repo 4 | yum_repository: 5 | name: baseos-84 6 | description: CentOS Linux 8.4.2105 - BaseOS 7 | baseurl: https://vault.centos.org/$contentdir/8.4.2105/BaseOS/$basearch/os/ 8 | enabled: no 9 | gpgcheck: no 10 | - name: Add Centos 8.4.2105 AppStream repo 11 | yum_repository: 12 | name: appstream-84 13 | description: CentOS Linux 8.4.ex2105 - AppStream 14 | baseurl: https://vault.centos.org/$contentdir/8.4.2105/AppStream/$basearch/os/ 15 | enabled: no 16 | gpgcheck: no 17 | - name: Install a package which isn't in CentOS 8.5 anymore 18 | yum: 19 | name: subscription-manager-initial-setup-addon 20 | enablerepo: "appstream-84,baseos-84" 21 | state: present 22 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/unavailable-package/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Package removed from CentOS 8.5 3 | description: | 4 | Verify that Convert2RHEL can correctly handle removal of package from the 5 | excluded list that is listed under the configuration files. 6 | This package is not available in the latest version of CentOS 8.5. 7 | The package that needs to be removed is installed during the plan 8 | preparation phase using an ansible playbook. 9 | The test itself verifies the presence of the package on the system 10 | and proceeds with the conversion. 11 | 12 | 13 | /package_removed_from_centos_85: 14 | test: pytest -m test_package_removed_from_centos_85 15 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/unavailable-package/test_pkg_removed_from_centos_85.py: -------------------------------------------------------------------------------- 1 | from conftest import TEST_VARS 2 | 3 | 4 | def test_package_removed_from_centos_85(convert2rhel, shell): 5 | """ 6 | Verify that Convert2RHEL can correctly handle removal of package from the 7 | excluded list that is listed under the configuration files. This test 8 | installs the package that need to be removed during the plan preparation phase 9 | using an ansible playbook. 10 | The test itself verifies the presence of the package on the system 11 | and proceeds with the conversion. 12 | """ 13 | assert shell("rpm -qi subscription-manager-initial-setup-addon").returncode == 0 14 | 15 | with convert2rhel( 16 | "-y --serverurl {} --username {} --password {} --debug".format( 17 | TEST_VARS["RHSM_SERVER_URL"], 18 | TEST_VARS["RHSM_SCA_USERNAME"], 19 | TEST_VARS["RHSM_SCA_PASSWORD"], 20 | ) 21 | ) as c2r: 22 | c2r.expect("Conversion successful!") 23 | assert c2r.exitstatus == 0 24 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/yum-conf-exclude-packages/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Exclude kernel* and redhat-release-server packages in yum conf 3 | description+: | 4 | This tests verifies that it is possible to do a full conversion when 5 | the all kernel packages (kernel*) and redhat-release-server is set to be excluded 6 | in the yum configuration file. 7 | 8 | tag+: 9 | - kernel 10 | link: 11 | - verifies: https://issues.redhat.com/browse/RHELC-774 12 | /yum_conf_exclude_packages: 13 | test: pytest -m test_yum_conf_exclude_packages 14 | -------------------------------------------------------------------------------- /tests/integration/tier1/destructive/yum-conf-exclude-packages/test_yum_conf_exclude_packages.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from conftest import TEST_VARS 4 | 5 | 6 | @pytest.mark.parametrize("yum_conf_exclude", [["kernel*", "redhat-release-server"]], indirect=True) 7 | def test_yum_conf_exclude_packages(convert2rhel, yum_conf_exclude): 8 | """ 9 | Verify, the conversion does not raise: 10 | 'Could not find any kernel from repositories to compare against the loaded kernel.' 11 | When `exclude=kernel kernel-core redhat-release-server` is defined in yum.conf 12 | Verify IS_LOADED_KERNEL_LATEST has succeeded is raised. 13 | Reference ticket: https://issues.redhat.com/browse/RHELC-774 14 | """ 15 | with convert2rhel( 16 | "-y --serverurl {} --username {} --password {} --debug".format( 17 | TEST_VARS["RHSM_SERVER_URL"], 18 | TEST_VARS["RHSM_SCA_USERNAME"], 19 | TEST_VARS["RHSM_SCA_PASSWORD"], 20 | ) 21 | ) as c2r: 22 | c2r.expect("IS_LOADED_KERNEL_LATEST has succeeded") 23 | 24 | assert c2r.exitstatus == 0 25 | -------------------------------------------------------------------------------- /tests/integration/tier1/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Tier1 tests 3 | 4 | description+: | 5 | Set of tests/plans of less frequency demands. 6 | tier1 is run when the PR gets merged to the main branch. 7 | 8 | 9 | tier: 1 10 | -------------------------------------------------------------------------------- /tests/integration/tier1/non-destructive/httpd-package-transaction-error/main.fmf: -------------------------------------------------------------------------------- 1 | summary: | 2 | Test that verifies that having httpd installed is not causing transaction error. 3 | description: | 4 | The yum transaction error happened when some packages depends on each 5 | other. When a package had dependency on some excluded package (like centos-logos) 6 | which was removed during the conversion then the package had missing dependency. 7 | If reinstall of some package happens that brings those dependencies into the transaction 8 | the error was raised. The problem was mostly caused by the httpd package installed on the 9 | system. 10 | 11 | tag+: 12 | - httpd-package-transaction-error 13 | 14 | /httpd_package_transaction_error: 15 | enabled: false 16 | link: https://issues.redhat.com/browse/RHELC-1130 17 | adjust+: 18 | enabled: true 19 | when: distro == centos-7 20 | because: The bug is reproducible only on centos-7 21 | test: | 22 | pytest -m test_httpd_package_transaction_error 23 | -------------------------------------------------------------------------------- /tests/integration/tier1/non-destructive/main.fmf: -------------------------------------------------------------------------------- 1 | summary+: | 2 | Set of non-destructive tests tier 1 3 | 4 | description+: | 5 | All tests are non-destructive, meaning there is not a full conversion being done. 6 | The latest point of verification for these tests is PONR (point of no return). 7 | The preparation and cleanup phase is implemented in the test itself. 8 | 9 | tag+: 10 | - non-destructive 11 | 12 | environment+: 13 | C2R_TESTS_NONDESTRUCTIVE: 1 14 | --------------------------------------------------------------------------------