diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 657ff1e627..070404b545 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -11,8 +11,7 @@ from collections import namedtuple from contextlib import contextmanager -from fileinput import FileInput -from typing import ContextManager, Optional +from typing import ContextManager import click import pexpect @@ -229,6 +228,12 @@ def fixture_subman(): yield + # The "pre_registered system" test requires to remain registered even after the conversion is completed, + # so the check "enabled repositories" after the conversion can be executed. + if "C2R_TESTS_SUBMAN_REMAIN_REGISTERED" not in os.environ: + subman.unregister() + + # We do not need to spend time on performing the cleanup for some test cases (destructive) if "C2R_TESTS_NONDESTRUCTIVE" in os.environ: subman.clean_up() @@ -376,97 +381,6 @@ def factory( return factory -@dataclasses.dataclass -class OsRelease: - """Dataclass representing the content of /etc/os-release.""" - - name: str - version: str - id: str - id_like: str - version_id: str - pretty_name: str - home_url: str - bug_report_url: str - ansi_color: Optional[str] = None - cpe_name: Optional[str] = None - platform_id: Optional[str] = None - - @classmethod - def create_from_file(cls, file: Path): - assert file.exists(), f"File doesn't exist: {str(file)}" - res = {} - with open(file) as os_release_f: - for line in os_release_f: - try: - param, value = line.strip().split("=") - except ValueError: - # we're skipping lines which can't be split based on = - pass - else: - if param.lower() in cls.__annotations__: - res[param.lower()] = value.strip('"') - return cls(**res) - - -@pytest.fixture() -def os_release(): - return OsRelease.create_from_file(Path("/etc/os-release")) - - -class ConfigUtils: - """Convenient features to work with configs (or any other text files). - - Created specifically to simplify writing integration tests, which requires - adjusting some configs. - """ - - def __init__(self, config_path: Path): - self.config_path = config_path - - @contextmanager - def replace_line(self, pattern: str, repl: str): - """Iterates over config file lines and do re.sub for each line. - - Parameters are the same as in re.sub - (https://docs.python.org/3/library/re.html#re.sub) - - Example: - >>> with c2r_config.replace_line(pattern="releasever=.*", repl=f"releasever=9"): - >>> # do something here (the config is changed) - >>> pass - >>> # config is restored at this point - """ - logger.info(f"Scanning {str(self.config_path)} for {repr(pattern)} and replace with {repr(repl)}") - search = re.compile(pattern) - backup_suffix = ".bak" - try: - with FileInput(files=[str(self.config_path)], inplace=True, backup=backup_suffix) as f: - for line in f: - new_line = search.sub(repl, line) - if line != new_line: - logger.debug(f"{repr(line.strip())} replaced with\n{repr(new_line.strip())}") - # need to write to stdout to write the line to the file - print(new_line, end="") - yield - finally: - backup_config = self.config_path.with_suffix(self.config_path.suffix + backup_suffix) - backup_config.replace(self.config_path) - logger.debug("ConfigUtils file was restored to the origin state") - - -@pytest.fixture() -def c2r_config(os_release): - """ConfigUtils object with already loaded convert2rhel config.""" - release_id2conf = {"centos": "centos", "ol": "oracle", "almalinux": "almalinux", "rocky": "rocky"} - config_path = ( - Path("/usr/share/convert2rhel/configs/") - / f"{release_id2conf[os_release.id]}-{os_release.version[0]}-x86_64.cfg" - ) - assert config_path.exists(), f"Can't find Convert2RHEL config file.\n{str(config_path)} - does not exist." - return ConfigUtils(config_path) - - class SystemInformationRelease: """ Helper class. @@ -503,25 +417,6 @@ class SystemInformationRelease: system_release = "{}-{}.{}".format(distribution, version.major, version.minor) -@pytest.fixture() -def config_at(): - """Factory of the ConfigUtils object. - - Created for simplicity injecting it into your testing unit (no need to import). - - Example: - >>> with config_at(Path("/etc/system-release")).replace_line( - >>> "release .+", - >>> f"release {os_release.version[0]}.1.1111", - >>> ): - """ - - def factory(path: Path) -> ConfigUtils: - return ConfigUtils(path) - - return factory - - @pytest.fixture() def log_file_data(): """ @@ -559,7 +454,7 @@ def remove_repositories(shell, backup_directory): @pytest.fixture -def pre_registered(shell, request): +def pre_registered(shell, request, fixture_subman): """ A fixture to install subscription manager and pre-register the system prior to the convert2rhel run. We're using the client-tools-for-rhel--rpms repository to install the subscription-manager package from. @@ -568,8 +463,6 @@ def pre_registered(shell, request): Can be parametrized by requesting a different KEY from the TEST_VARS file. @pytest.mark.parametrize("pre_registered", [("DIFFERENT_USERNAME", "DIFFERENT_PASSWORD")], indirect=True) """ - subman = SubscriptionManager() - username = TEST_VARS["RHSM_SCA_USERNAME"] password = TEST_VARS["RHSM_SCA_PASSWORD"] # Use custom keys when the fixture is parametrized @@ -579,18 +472,16 @@ def pre_registered(shell, request): password = TEST_VARS[password_key] print(">>> Using parametrized username and password requested in the fixture.") - subman.set_up_requirements() - # Register the system assert ( shell( - "subscription-manager register --serverurl {} --username {} --password {}".format( + "subscription-manager register --serverurl {0} --username {1} --password {2}".format( TEST_VARS["RHSM_SERVER_URL"], username, password ), hide_command=True, ).returncode == 0 - ) + ), f"Failed to pre-register the system. The subscription manager call has failed." rhsm_uuid_command = "subscription-manager identity | grep identity" @@ -612,15 +503,6 @@ def pre_registered(shell, request): # Validate it matches with UUID prior to the conversion assert original_registration_uuid == post_c2r_registration_uuid - # The "pre_registered system" test requires to remain registered even after the conversion is completed, - # so the check "enabled repositories" after the conversion can be executed. - if "C2R_TESTS_SUBMAN_REMAIN_REGISTERED" not in os.environ: - subman.unregister() - - # We do not need to spend time on performing the cleanup for some test cases (destructive) - if "C2R_TESTS_NONDESTRUCTIVE" in os.environ: - subman.clean_up() - @pytest.fixture() def hybrid_rocky_image(shell): @@ -644,25 +526,25 @@ def hybrid_rocky_image(shell): def environment_variables(request): """ Fixture. - Sets and unsets required environment variables. - Environment variable(s) needs to be passed as a list(s) to pytest parametrize. + Set and unset required environment variables. Usage: - @pytest.mark.parametrize("envars", [["LIST", "OF"], ["ENVIRONMENT", "VARIABLES"]]) + @pytest.mark.parametrize("environment_variables", ["CONVERT2RHEL_UNSUPPORTED"], indirect=True) + @pytest.mark.parametrize("environment_variables", [["FIRST", "TEST", "EXECUTION"], ["SECOND", "TEST", "EXECUTION"]], indirect=True) """ - def _set_env_var(envars): - for envar in envars: - os.environ[envar] = "1" + if hasattr(request, "param"): + env_vars = request.param + if not isinstance(env_vars, list): + env_vars = [env_vars] - yield _set_env_var + for e in env_vars: + os.environ[e] = "1" - def _unset_env_var(envars): - for envar in envars: - if envar in os.environ: - del os.environ[envar] - assert envar not in os.environ + yield - return _unset_env_var + for e in env_vars: + os.environ.pop(e, None) + assert e not in os.environ, f"The removal of the environment variable - '{e}' failed" @pytest.fixture(scope="function") diff --git a/tests/integration/tier0/destructive/conversion-method/main.fmf b/tests/integration/tier0/destructive/conversion-method/main.fmf index bdcb69e0f6..0b219cbd73 100644 --- a/tests/integration/tier0/destructive/conversion-method/main.fmf +++ b/tests/integration/tier0/destructive/conversion-method/main.fmf @@ -94,6 +94,8 @@ order: 49 description: | Verify that Convert2RHEL is working properly when ELS repositories are used during the conversion. Verify that the correct repositories are enabled after the conversion (in one of the check-after-conversion tests). + environment+: + C2R_TESTS_SUBMAN_REMAIN_REGISTERED: 1 tag+: - rhsm-els-conversion test: pytest -m test_rhsm_with_els_system_conversion diff --git a/tests/integration/tier0/non-destructive/kernel-modules/test_unsupported_kmod.py b/tests/integration/tier0/non-destructive/kernel-modules/test_unsupported_kmod.py index 131684a52f..e2a783ee1b 100644 --- a/tests/integration/tier0/non-destructive/kernel-modules/test_unsupported_kmod.py +++ b/tests/integration/tier0/non-destructive/kernel-modules/test_unsupported_kmod.py @@ -48,16 +48,15 @@ def test_inhibitor_with_unavailable_kmod_loaded(kmod_in_different_directory, con assert c2r.exitstatus == 2 -@pytest.mark.parametrize("envars", [["CONVERT2RHEL_ALLOW_UNAVAILABLE_KMODS"]]) +@pytest.mark.parametrize("environment_variables", ["CONVERT2RHEL_ALLOW_UNAVAILABLE_KMODS"], indirect=True) def test_override_inhibitor_with_unavailable_kmod_loaded( - kmod_in_different_directory, convert2rhel, environment_variables, envars + kmod_in_different_directory, convert2rhel, environment_variables ): """ This test verifies that setting the environment variable "CONVERT2RHEL_ALLOW_UNAVAILABLE_KMODS" will override the check error when there is an kernel module unavailable in RHEL detected. The environment variable is set through the test metadata. """ - environment_variables(envars) with convert2rhel( "--serverurl {} --username {} --password {} --debug".format( TEST_VARS["RHSM_SERVER_URL"], @@ -108,8 +107,8 @@ def test_inhibitor_with_force_loaded_tainted_kmod(shell, convert2rhel, forced_km assert c2r.exitstatus == 1 -@pytest.mark.parametrize("envars", [["CONVERT2RHEL_TAINTED_KERNEL_MODULE_CHECK_SKIP"]]) -def test_override_inhibitor_with_tainted_kmod(shell, convert2rhel, forced_kmods, environment_variables, envars): +@pytest.mark.parametrize("environment_variables", ["CONVERT2RHEL_TAINTED_KERNEL_MODULE_CHECK_SKIP"], indirect=True) +def test_override_inhibitor_with_tainted_kmod(shell, convert2rhel, forced_kmods, environment_variables): """ In this test case we force load kmod and verify that the TAINTED_KMODS.TAINTED_KMODS_DETECTED is overridable by setting the environment variable 'CONVERT2RHEL_TAINTED_KERNEL_MODULE_CHECK_SKIP' @@ -117,7 +116,6 @@ def test_override_inhibitor_with_tainted_kmod(shell, convert2rhel, forced_kmods, Force loaded kmods are denoted (FE) where F = module was force loaded E = unsigned module was loaded. Convert2RHEL sees force loaded kmod as tainted. """ - environment_variables(envars) with convert2rhel( "--serverurl {} --username {} --password {} --debug".format( TEST_VARS["RHSM_SERVER_URL"], diff --git a/tests/integration/tier0/non-destructive/kernel/test_custom_kernel.py b/tests/integration/tier0/non-destructive/kernel/test_custom_kernel.py index 7407e03fe4..9484ae5625 100644 --- a/tests/integration/tier0/non-destructive/kernel/test_custom_kernel.py +++ b/tests/integration/tier0/non-destructive/kernel/test_custom_kernel.py @@ -63,9 +63,10 @@ def custom_kernel(shell, hybrid_rocky_image, backup_directory): custom_kernel_installed = None # Create a temporary file to store the original kernel NVRA kernel_info_storage = os.path.join(backup_directory, "original-kernel") - # Store the current running kernel NVRA in a file - shell("echo $(uname -r) >> %s" % kernel_info_storage) if os.environ["TMT_REBOOT_COUNT"] == "0": + # Store the current running kernel NVRA in a file + shell("echo $(uname -r) > %s" % kernel_info_storage) + # The version of yum on el7 like systems does not allow the --repofrompath option. # Therefore, we need to install the rpm directly if SystemInformationRelease.version.major == 7: @@ -101,9 +102,6 @@ def custom_kernel(shell, hybrid_rocky_image, backup_directory): with open(kernel_info_storage, "r") as f: original_kernel = f.readline().rstrip() original_kernel_title = get_full_kernel_title(shell, kernel=original_kernel) - # Install back the CentOS 8.5 original kernel - if "centos-8-latest" in SYSTEM_RELEASE_ENV: - assert shell(f"yum reinstall -y kernel").returncode == 0 workaround_grub_setup(shell) assert shell(f"grub2-set-default '{original_kernel_title}'").returncode == 0 diff --git a/tests/integration/tier0/non-destructive/modified-releasever/test_modified_releasever.py b/tests/integration/tier0/non-destructive/modified-releasever/test_modified_releasever.py index 18701dbf0c..b9d7b12ecc 100644 --- a/tests/integration/tier0/non-destructive/modified-releasever/test_modified_releasever.py +++ b/tests/integration/tier0/non-destructive/modified-releasever/test_modified_releasever.py @@ -1,83 +1,77 @@ -import os.path - from pathlib import Path import pytest -from conftest import TEST_VARS +from conftest import TEST_VARS, SystemInformationRelease @pytest.fixture(scope="function") -def c2r_config_releasever(shell, backup_directory): +def backup_files(request, shell, backup_directory): """ Fixture. - Modify the releasever inside the convert2rhel configs. - Restore back from backup after the test. + Backup files or directories before the test + and restore them after the test finishes. Need to be parametrized. + Examples: + @pytest.mark.parametrize("backup_files", ["/usr/share/convert2rhel/configs/"], indirect=True) + @pytest.mark.parametrize("backup_files", ["/etc/system-release"], indirect=True) """ + if not hasattr(request, "param"): + # Nothing to backup.. + print("\n 'backup_files' fixture called without parameter, doing nothing") + return + path_to_backup = Path(request.param) + + assert path_to_backup.exists(), f"Provided path '{path_to_backup}' to the 'backup_files' fixture does not exists" - # Backup configs - path_to_configs = "/usr/share/convert2rhel/configs/" - assert shell(f"cp -r {path_to_configs} {backup_directory}").returncode == 0 + # Create the backup + assert shell(f"cp -r {path_to_backup.as_posix()} {backup_directory}").returncode == 0 yield # Restore configs - assert shell(f"mv -f {backup_directory}/* {path_to_configs}").returncode == 0 + shell(f"rm -rf {path_to_backup.as_posix()}") + assert shell(f"mv -f {backup_directory}/* {path_to_backup.as_posix()}").returncode == 0 -def test_releasever_modified_in_c2r_config(convert2rhel, os_release, c2r_config, shell, c2r_config_releasever): +@pytest.mark.parametrize("backup_files", ["/usr/share/convert2rhel/configs/"], indirect=True) +def test_releasever_modified_in_c2r_config(backup_files, convert2rhel, shell): """ Verify that releasever changes in /usr/share/convert2rhel/configs/ take precedence. """ - with c2r_config.replace_line(pattern="releasever=.*", repl="releasever=333"): - with convert2rhel( - "-y --serverurl {} --username {} --password {} --debug".format( - TEST_VARS["RHSM_SERVER_URL"], - TEST_VARS["RHSM_SCA_USERNAME"], - TEST_VARS["RHSM_SCA_PASSWORD"], - ), - unregister=True, - ) as c2r: - c2r.expect("--releasever=333") - c2r.sendcontrol("c") - assert c2r.exitstatus == 1 - - -@pytest.fixture(scope="function") -def system_release_backup(shell, backup_directory): - """ - Fixture. - Backup /etc/system-release before the test makes modifications to it. - Restore the file after the test - """ - # Backup /etc/system-release - backup_file = os.path.join(backup_directory, "system-release.bkp") - assert shell(f"cp /etc/system-release {backup_file}").returncode == 0 - - yield - - # Restore system-release - assert shell(f"mv -f {backup_file} /etc/system-release").returncode == 0 - - -def test_inhibitor_releasever_noexistent_release(convert2rhel, config_at, os_release, shell, system_release_backup): + config_file_name = f"{SystemInformationRelease.distribution}-{SystemInformationRelease.version.major}-x86_64.cfg" + shell(f"sed -i 's/releasever=.*/releasever=420/g' /usr/share/convert2rhel/configs/{config_file_name}") + with convert2rhel( + "analyze -y --serverurl {} --username {} --password {} --debug".format( + TEST_VARS["RHSM_SERVER_URL"], + TEST_VARS["RHSM_SCA_USERNAME"], + TEST_VARS["RHSM_SCA_PASSWORD"], + ), + unregister=True, + ) as c2r: + c2r.expect("--releasever=420") + c2r.expect_exact("ERROR - (ERROR) ENSURE_KERNEL_MODULES_COMPATIBILITY::PROBLEM_WITH_PACKAGE_REPO") + + assert c2r.exitstatus == 0 + + +@pytest.mark.parametrize("backup_files", ["/etc/system-release"], indirect=True) +def test_inhibitor_releasever_noexistent_release(backup_files, convert2rhel, shell): """ Verify that running not allowed OS release inhibits the conversion. - Modify the /etc/system-release file to set the releasever to an unsupported version (e.g. x.1.1111) + Modify the /etc/system-release file to set the releasever to an unsupported version (e.g. x.11.1111) """ - with config_at(Path("/etc/system-release")).replace_line( - "release .+", - f"release {os_release.version[0]}.11.1111", - ): - with convert2rhel( - "-y --serverurl {} --username {} --password {} --debug".format( - TEST_VARS["RHSM_SERVER_URL"], - TEST_VARS["RHSM_SCA_USERNAME"], - TEST_VARS["RHSM_SCA_PASSWORD"], - ), - unregister=True, - ) as c2r: - c2r.expect( - f"CRITICAL - {os_release.name} of version {os_release.version[0]}.11 is not allowed for conversion." - ) - assert c2r.exitstatus == 1 + shell( + f"sed -i 's/release {SystemInformationRelease.version.major}.{SystemInformationRelease.version.minor}/release {SystemInformationRelease.version.major}.11.11111/' /etc/system-release" + ) + with convert2rhel( + "analyze -y --serverurl {} --username {} --password {} --debug".format( + TEST_VARS["RHSM_SERVER_URL"], + TEST_VARS["RHSM_SCA_USERNAME"], + TEST_VARS["RHSM_SCA_PASSWORD"], + ), + unregister=True, + ) as c2r: + c2r.expect( + f"CRITICAL - .* of version {SystemInformationRelease.version.major}.11 is not allowed for conversion." + ) + assert c2r.exitstatus == 1