diff --git a/tests/install_upgrade_operators/product_upgrade/conftest.py b/tests/install_upgrade_operators/product_upgrade/conftest.py index 6452705b0e..da1cce39b7 100644 --- a/tests/install_upgrade_operators/product_upgrade/conftest.py +++ b/tests/install_upgrade_operators/product_upgrade/conftest.py @@ -4,6 +4,7 @@ import pytest from ocp_resources.cluster_version import ClusterVersion +from ocp_resources.image_digest_mirror_set import ImageDigestMirrorSet from ocp_resources.resource import ResourceEditor from ocp_utilities.monitoring import Prometheus from packaging.version import Version @@ -11,6 +12,9 @@ from tests.install_upgrade_operators.constants import WORKLOAD_UPDATE_STRATEGY_KEY_NAME, WORKLOADUPDATEMETHODS from tests.install_upgrade_operators.product_upgrade.utils import ( + KONFLUX_IDMS_NAME, + KONFLUX_MIRROR_BASE_URL, + apply_konflux_idms, approve_cnv_upgrade_install_plan, extract_ocp_version_from_ocp_image, get_alerts_fired_during_upgrade, @@ -19,6 +23,7 @@ get_nodes_labels, get_nodes_taints, get_shortest_upgrade_path, + idms_has_all_mirrors, perform_cnv_upgrade, run_ocp_upgrade_command, set_workload_update_methods_hco, @@ -31,7 +36,12 @@ ) from tests.install_upgrade_operators.utils import wait_for_operator_condition from tests.upgrade_params import EUS -from utilities.constants import HCO_CATALOG_SOURCE, HOTFIX_STR, TIMEOUT_10MIN, NamespacesNames +from utilities.constants import ( + HCO_CATALOG_SOURCE, + HOTFIX_STR, + TIMEOUT_10MIN, + NamespacesNames, +) from utilities.data_collector import ( get_data_collector_base_directory, ) @@ -85,47 +95,45 @@ def nodes_labels_before_upgrade(nodes, cnv_upgrade): return get_nodes_labels(nodes=nodes, cnv_upgrade=cnv_upgrade) +@pytest.fixture(scope="session") +def required_konflux_mirrors(cnv_target_version, cnv_current_version): + target = Version(version=cnv_target_version) + current = Version(version=cnv_current_version) + return [ + f"{KONFLUX_MIRROR_BASE_URL}/v{target.major}-{minor}" for minor in range(target.minor, current.minor - 1, -1) + ] + + @pytest.fixture() -def updated_image_content_source_policy( - admin_client, - nodes, - tmpdir_factory, - active_machine_config_pools, - machine_config_pools_conditions, - cnv_image_url, +def updated_konflux_idms( cnv_image_name, + nodes, cnv_source, - cnv_target_version, - cnv_registry_source, - pull_secret_directory, - generated_pulled_secret, + required_konflux_mirrors, is_disconnected_cluster, - is_idms_cluster, + active_machine_config_pools, + machine_config_pools_conditions, ): - """ - Creates a new ImageContentSourcePolicy file with a given CNV image and applies it to the cluster. - """ + """Ensures the Konflux IDMS contains the required mirror entries for the CNV upgrade target version.""" if is_disconnected_cluster: - LOGGER.warning("Skip applying ICSP/IDMS in a disconnected setup.") + LOGGER.warning("Skip applying IDMS in a disconnected setup.") return if cnv_source == HOTFIX_STR: - LOGGER.info("ICSP updates skipped as upgrading using production source/upgrade to hotfix") + LOGGER.info("IDMS updates skipped as upgrading using production source/upgrade to hotfix") return - file_path = get_generated_icsp_idms( - image_url=cnv_image_url, - registry_source=cnv_registry_source["source_map"], - generated_pulled_secret=generated_pulled_secret, - pull_secret_directory=pull_secret_directory, - is_idms_cluster=is_idms_cluster, - ) - apply_icsp_idms( - file_paths=[file_path], + + idms = ImageDigestMirrorSet(name=KONFLUX_IDMS_NAME) + if idms.exists and idms_has_all_mirrors(idms=idms, required_mirrors=required_konflux_mirrors): + LOGGER.info(f"IDMS {KONFLUX_IDMS_NAME} already contains all required mirrors.") + return + + apply_konflux_idms( + idms=idms, + required_mirrors=required_konflux_mirrors, machine_config_pools=active_machine_config_pools, mcp_conditions=machine_config_pools_conditions, nodes=nodes, - is_idms_file=is_idms_cluster, - delete_file=True, ) diff --git a/tests/install_upgrade_operators/product_upgrade/test_upgrade.py b/tests/install_upgrade_operators/product_upgrade/test_upgrade.py index 5f67ca8775..6ef24f1135 100644 --- a/tests/install_upgrade_operators/product_upgrade/test_upgrade.py +++ b/tests/install_upgrade_operators/product_upgrade/test_upgrade.py @@ -54,7 +54,7 @@ def test_cnv_upgrade_process( cnv_upgrade_stream, fired_alerts_before_upgrade, disabled_default_sources_in_operatorhub, - updated_image_content_source_policy, + updated_konflux_idms, updated_custom_hco_catalog_source_image, updated_cnv_subscription_source, approved_cnv_upgrade_install_plan, diff --git a/tests/install_upgrade_operators/product_upgrade/utils.py b/tests/install_upgrade_operators/product_upgrade/utils.py index cd07e8a20c..0d4464a462 100644 --- a/tests/install_upgrade_operators/product_upgrade/utils.py +++ b/tests/install_upgrade_operators/product_upgrade/utils.py @@ -13,9 +13,11 @@ from ocp_resources.cluster_service_version import ClusterServiceVersion from ocp_resources.cluster_version import ClusterVersion from ocp_resources.hyperconverged import HyperConverged +from ocp_resources.image_digest_mirror_set import ImageDigestMirrorSet from ocp_resources.kubevirt import KubeVirt from ocp_resources.machine_config_pool import MachineConfigPool from ocp_resources.namespace import Namespace +from ocp_resources.node import Node from ocp_resources.resource import Resource, ResourceEditor from packaging.version import Version from pyhelper_utils.shell import run_command @@ -59,6 +61,9 @@ LOGGER = logging.getLogger(__name__) TIER_2_PODS_TYPE = "tier-2" +KONFLUX_IDMS_NAME = "zz-cnv-icsp-fallback" +KONFLUX_MIRROR_BASE_URL = "quay.io/openshift-virtualization/konflux-builds" +KONFLUX_IDMS_SOURCE = "registry.redhat.io/container-native-virtualization" # list of whitelisted alerts WHITELIST_ALERTS_UPGRADE_LIST = ["OutdatedVirtualMachineInstanceWorkloads"] @@ -713,3 +718,54 @@ def _get_updated_odf_csv(_target_version: str, _admin_client: DynamicClient) -> if not sample: return LOGGER.info(f"Following odf csvs are not updated: {','.join(sample)}") + + +def apply_konflux_idms( + idms: ImageDigestMirrorSet, + required_mirrors: list[str], + machine_config_pools: list[MachineConfigPool], + mcp_conditions: dict[str, list[dict[str, str]]], + nodes: list[Node], +) -> None: + """Creates or patches the Konflux IDMS with the required mirror entries. + + Args: + idms: The Konflux IDMS resource to create or patch. + required_mirrors: Konflux mirror URLs to set on the IDMS. + machine_config_pools: Active machine config pools to pause/wait. + mcp_conditions: Initial MCP conditions for tracking update progress. + nodes: Cluster nodes to verify readiness after MCP update. + """ + image_digest_mirrors = [{"source": KONFLUX_IDMS_SOURCE, "mirrors": required_mirrors}] + + LOGGER.info("Pausing MCP updates while modifying IDMS.") + with ResourceEditor(patches={mcp: {"spec": {"paused": True}} for mcp in machine_config_pools}): + if idms.exists: + LOGGER.info(f"Patching IDMS {KONFLUX_IDMS_NAME} with mirrors: {required_mirrors}") + ResourceEditor(patches={idms: {"spec": {"imageDigestMirrors": image_digest_mirrors}}}).update() + else: + LOGGER.info(f"Creating IDMS {KONFLUX_IDMS_NAME} with mirrors: {required_mirrors}") + ImageDigestMirrorSet( + name=KONFLUX_IDMS_NAME, + image_digest_mirrors=image_digest_mirrors, + teardown=False, + ).deploy(wait=True) + + LOGGER.info("Wait for MCP update after IDMS modification.") + wait_for_mcp_update_completion( + machine_config_pools_list=machine_config_pools, + initial_mcp_conditions=mcp_conditions, + nodes=nodes, + ) + + +def idms_has_all_mirrors(idms: ImageDigestMirrorSet, required_mirrors: list[str]) -> bool: + """Returns True if the IDMS already contains all required Konflux mirror entries.""" + source_entry = next( + (entry for entry in idms.instance.spec.imageDigestMirrors if entry["source"] == KONFLUX_IDMS_SOURCE), + None, + ) + if not source_entry: + return False + existing_urls = {str(mirror) for mirror in source_entry["mirrors"]} + return all(mirror in existing_urls for mirror in required_mirrors)