Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from _pytest.runner import CallInfo
from kubernetes.dynamic.exceptions import ConflictError
from ocp_resources.resource import get_client
from packaging.version import Version

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Execution Plan

Run smoke tests: False
No dependency path traced from any smoke-marked test to modified symbols. The six smoke files (, , , , , ) do not use EUS upgrade fixtures or call wait_for_mcp_update_completion / wait_for_mcp_update_end. The utilities/operator.py changes are backward-compatible (added timeout default param).

Run gating tests: True
Dependency path:

  • tests/virt/upgrade/test_upgrade_virt.py (gating) → @pytest.mark.usefixtures("virt_launcher_images_from_csv_before_upgrade")get_virt_launcher_images_from_csv() in tests/virt/upgrade/utils.py (renamed from get_virt_launcher_image_from_csv, return type changed strset[str])
  • tests/virt/upgrade/test_upgrade_virt.py (gating) → unupdated_vmi_pods_names fixture → validate_vms_pod_updated(expected_virt_launcher_images=...) (signature changed to accept set[str])
  • tests/virt/upgrade/test_upgrade_virt.py (gating) → csv_after_upgrade fixture → no longer falls back to eus_hco_target_csv_name

Affected tests to run

  • tests/virt/upgrade/test_upgrade_virt.py (gating) — fixture chain refactored: virt_launcher_images_from_csv_before_upgrade (renamed+returns set), virt_migratable_vms (replaces migratable_vms+upgrade_namespaces), csv_after_upgrade simplified
  • tests/install_upgrade_operators/product_upgrade/test_eus_upgrade.py (eus_upgrade) — full EUS upgrade path reworked: now driven by --cnv-version/--cnv-image instead of --eus-cnv-target-version; uses build_eus_upgrade_path_dict and created_target_hco_csv

Real tests (cluster required)

Root conftest.py changes affect pytest_cmdline_main at session startup: --eus-cnv-target-version option removed; EUS now requires --cnv-version and --cnv-image; odd-minor CNV version now raises a ValueError at startup (guarded by not config.option.collectonly).

Error path (validate odd-minor rejection — requires real cluster, not collection-only):

pytest tests/install_upgrade_operators/product_upgrade/test_eus_upgrade.py   --upgrade=eus --cnv-version=4.21.0 --cnv-image=<image> --eus-ocp-images=<img1>,<img2>

Expected: ValueError: EUS target version 4.21.0 must have an even minor version

Happy path (collection smoke-check with even-minor version):

pytest tests/install_upgrade_operators/product_upgrade/test_eus_upgrade.py   --upgrade=eus --cnv-version=4.22.0 --cnv-image=NA --eus-ocp-images=NA,NA --collect-only

Expected: session starts normally, tests collected without error

from pyhelper_utils.shell import run_command
from pytest import Item
from pytest_testconfig import config as py_config
Expand Down Expand Up @@ -151,7 +152,6 @@ def pytest_addoption(parser):
"--eus-ocp-images",
help="Comma-separated OCP images to use for EUS-to-EUS upgrade.",
)
install_upgrade_group.addoption("--eus-cnv-target-version", help="target CNV version for eus upgrade")
install_upgrade_group.addoption(
"--upgrade-skip-default-sc-setup",
help="Skip the fixture that changes the default sc in upgrade lane",
Expand Down Expand Up @@ -328,18 +328,21 @@ def pytest_cmdline_main(config):
if upgrade_option == "ocp" and not config.getoption("ocp_image"):
raise ValueError("Running with --upgrade ocp: Missing --ocp-image")

if upgrade_option == "cnv":
if upgrade_option in ("cnv", "eus"):
if not config.getoption("cnv_version"):
raise ValueError("Missing --cnv-version")
if not config.getoption("cnv_image"):
if config.getoption("cnv_source") != "production":
if upgrade_option == "eus" or config.getoption("cnv_source") != "production":
raise ValueError("Missing --cnv-image")

if upgrade_option == "eus":
if upgrade_option == "eus" and not config.option.collectonly:
cnv_version = config.getoption("cnv_version")
if Version(version=cnv_version).minor % 2:
raise ValueError(f"EUS target version {cnv_version} must have an even minor version")
eus_ocp_images = config.getoption("eus_ocp_images")
if not (eus_ocp_images and len(eus_ocp_images.split(",")) == 2):
raise ValueError(
f"Two OCP images are needed to perform EUS-to-EUS upgrade with --eus-ocp-images."
f"Two OCP images are needed for EUS-to-EUS upgrade with --eus-ocp-images."
f" Provided images: {eus_ocp_images}"
)

Expand Down Expand Up @@ -834,7 +837,7 @@ def is_skip_must_gather(node: Node) -> bool:

def get_inspect_command_namespace_string(node: Node, test_name: str) -> str:
namespace_str = ""
components = [key for key in NAMESPACE_COLLECTION.keys() if f"tests/{key}/" in test_name]
components = [key for key in NAMESPACE_COLLECTION if f"tests/{key}/" in test_name]
if not components:
LOGGER.warning(f"{test_name} does not require special data collection on failure")
else:
Expand Down
21 changes: 18 additions & 3 deletions docs/INSTALL_AND_UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,27 @@ To upgrade to cnv 4.Y.z, using the cnv image that has been shipped, following co
```

#### EUS upgrade
You must provide --eus-ocp-images via cli, which is two comma separated ocp images for EUS upgrade.
The default target cnv version will be 4.Y+2.0. Optionally, --eus-csv-target-version can be provided for 4.Y+2.z version.
EUS-to-EUS upgrades are only viable between even-numbered minor versions (e.g., 4.20 -> 4.22).

Parameters:

| Parameter Name | Requirement | Default Value | Possible Value |
|:------------------|:---------------:|:-------------:|:----------------------------:|
| `--cnv-version` | **Required** | - | 4.Y.z |
| `--cnv-image` | **Required** | - | -image path- |
| `--cnv-channel` | **Optional** | stable | stable, candidate, nightly |
| `--eus-ocp-images` | **Required** | - | comma-separated OCP images |

Command to run entire upgrade test suite for EUS upgrade, including pre and post upgrade validation:

```bash
--upgrade eus --eus-ocp-images <ocp_image_version_4.y+1.z>,<ocp_image_version_4.y+2.z> --eus-cnv-target-version <4.Y+2.z|None>
--upgrade eus --cnv-version <target_version> --cnv-image <cnv_image_to_upgrade_to> --eus-ocp-images <ocp_image_4.y+1.z>,<ocp_image_4.y+2.z>
```

Command to run only EUS upgrade test, without any pre/post validation:

```bash
-m eus_upgrade --upgrade eus --cnv-version <target_version> --cnv-image <cnv_image_to_upgrade_to> --eus-ocp-images <ocp_image_4.y+1.z>,<ocp_image_4.y+2.z>
```
#### Custom upgrade lanes

Expand Down
20 changes: 3 additions & 17 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
from ocp_resources.virtual_machine_instancetype import VirtualMachineInstancetype
from ocp_resources.virtual_machine_preference import VirtualMachinePreference
from ocp_utilities.monitoring import Prometheus
from packaging.version import Version, parse
from packaging.version import parse
from pytest_testconfig import config as py_config
from timeout_sampler import TimeoutSampler

Expand Down Expand Up @@ -1895,28 +1895,14 @@ def hco_target_csv_name(cnv_target_version):
return get_hco_csv_name_by_version(cnv_target_version=cnv_target_version) if cnv_target_version else None


@pytest.fixture(scope="session")
def eus_hco_target_csv_name(eus_target_cnv_version):
if eus_target_cnv_version is None:
LOGGER.warning("Cannot determine EUS HCO target CSV name: EUS target version is None (non-EUS version)")
return None
return get_hco_csv_name_by_version(cnv_target_version=eus_target_cnv_version)


@pytest.fixture(scope="session")
def cnv_target_version(pytestconfig):
return pytestconfig.option.cnv_version


@pytest.fixture(scope="session")
def eus_target_cnv_version(pytestconfig, cnv_current_version):
cnv_current_version = Version(version=cnv_current_version)
minor = cnv_current_version.minor
# EUS-to-EUS upgrades are only viable between even-numbered minor versions, return None if non-eus version
if minor % 2:
LOGGER.warning(f"EUS upgrade can not be performed from non-eus version: {cnv_current_version}")
return None
return pytestconfig.option.eus_cnv_target_version or f"{cnv_current_version.major}.{minor + 2}.0"
def cnv_channel(pytestconfig):
return pytestconfig.option.cnv_channel


@pytest.fixture()
Expand Down
96 changes: 52 additions & 44 deletions tests/install_upgrade_operators/product_upgrade/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@
)
from tests.install_upgrade_operators.product_upgrade.utils import (
approve_cnv_upgrade_install_plan,
build_eus_upgrade_path_dict,
extract_ocp_version_from_ocp_image,
get_alerts_fired_during_upgrade,
get_all_firing_cnv_alerts,
get_iib_images_of_cnv_versions,
get_nodes_labels,
get_nodes_taints,
get_shortest_upgrade_path,
perform_cnv_upgrade,
run_ocp_upgrade_command,
set_workload_update_methods_hco,
Expand All @@ -42,6 +41,7 @@
from utilities.constants import (
HCO_CATALOG_SOURCE,
TIMEOUT_10MIN,
TIMEOUT_180MIN,
NamespacesNames,
)
from utilities.data_collector import (
Expand All @@ -50,7 +50,6 @@
from utilities.infra import (
exit_pytest_execution,
generate_openshift_pull_secret_file,
get_csv_by_name,
get_prometheus_k8s_token,
get_related_images_name_and_version,
get_subscription,
Expand Down Expand Up @@ -324,24 +323,24 @@ def fired_alerts_during_upgrade(


@pytest.fixture(scope="session")
def eus_cnv_upgrade_path(eus_target_cnv_version):
if eus_target_cnv_version is None:
def eus_cnv_upgrade_path(
cnv_target_version,
cnv_current_version,
cnv_channel,
cnv_image_url,
):
if Version(version=cnv_current_version).minor % 2:
exit_pytest_execution(
message="EUS upgrade can not be performed from non-eus version", return_code=EUS_ERROR_CODE
message=f"EUS upgrade can not be performed from non-eus version: {cnv_current_version}",
return_code=EUS_ERROR_CODE,
filename="eus_upgrade_failure.txt",
)
# Get the shortest path to the target (EUS) version
upgrade_path_to_target_version = get_shortest_upgrade_path(target_version=eus_target_cnv_version)
# Get the shortest path to the intermediate (non-EUS) version
upgrade_path_to_intermediate_version = get_shortest_upgrade_path(
target_version=upgrade_path_to_target_version["startVersion"]
return build_eus_upgrade_path_dict(
current_cnv_version=cnv_current_version,
target_cnv_version=cnv_target_version,
target_channel=cnv_channel,
target_cnv_image_url=cnv_image_url,
)
# Return a dictionary with the versions and images for the EUS-to-EUS upgrade
upgrade_path = {
"non-eus": get_iib_images_of_cnv_versions(versions=upgrade_path_to_intermediate_version["versions"]),
EUS: get_iib_images_of_cnv_versions(versions=upgrade_path_to_target_version["versions"], errata_status="false"),
}
LOGGER.info(f"Upgrade path for EUS-to-EUS upgrade: {upgrade_path}")
return upgrade_path


@pytest.fixture(scope="session")
Expand Down Expand Up @@ -373,6 +372,7 @@ def eus_unpaused_worker_mcp(
machine_config_pools_list=worker_machine_config_pools,
initial_mcp_conditions=worker_machine_config_pools_conditions,
nodes=workers,
timeout=TIMEOUT_180MIN,
)


Expand Down Expand Up @@ -490,7 +490,7 @@ def triggered_non_eus_to_target_eus_ocp_upgrade(eus_ocp_image_urls):
@pytest.fixture()
def source_eus_to_non_eus_ocp_upgraded(
admin_client,
masters,
control_plane_nodes,
master_machine_config_pools,
ocp_version_eus_to_non_eus_from_image_url,
triggered_source_eus_to_non_eus_ocp_upgrade,
Expand All @@ -500,14 +500,14 @@ def source_eus_to_non_eus_ocp_upgraded(
machine_config_pools_list=master_machine_config_pools,
target_ocp_version=ocp_version_eus_to_non_eus_from_image_url,
initial_mcp_conditions=get_machine_config_pools_conditions(machine_config_pools=master_machine_config_pools),
nodes=masters,
nodes=control_plane_nodes,
)


@pytest.fixture()
def non_eus_to_target_eus_ocp_upgraded(
admin_client,
masters,
control_plane_nodes,
master_machine_config_pools,
ocp_version_non_eus_to_eus_from_image_url,
triggered_non_eus_to_target_eus_ocp_upgrade,
Expand All @@ -517,7 +517,7 @@ def non_eus_to_target_eus_ocp_upgraded(
machine_config_pools_list=master_machine_config_pools,
target_ocp_version=ocp_version_non_eus_to_eus_from_image_url,
initial_mcp_conditions=get_machine_config_pools_conditions(machine_config_pools=master_machine_config_pools),
nodes=masters,
nodes=control_plane_nodes,
)


Expand All @@ -526,17 +526,25 @@ def source_eus_to_non_eus_cnv_upgraded(
admin_client,
hco_namespace,
eus_cnv_upgrade_path,
cnv_subscription_scope_session,
cnv_registry_source,
hyperconverged_resource_scope_function,
updated_cnv_subscription_source,
):
for version, cnv_image in sorted(eus_cnv_upgrade_path["non-eus"].items()):
for version, build_info in sorted(
eus_cnv_upgrade_path["non-eus"].items(),
key=lambda item: Version(version=item[0]),
):
cnv_image = build_info["cnv_image_url"]
LOGGER.info(f"Cnv upgrade to version {version} using image: {cnv_image}")
perform_cnv_upgrade(
admin_client=admin_client,
cnv_image_url=cnv_image,
cr_name=hyperconverged_resource_scope_function.name,
hco_namespace=hco_namespace,
cnv_target_version=version.lstrip("v"),
cnv_target_version=version,
subscription=cnv_subscription_scope_session,
subscription_source=cnv_registry_source["cnv_subscription_source"],
subscription_channel=build_info["channel"],
)
LOGGER.info("Successfully performed cnv upgrades from source EUS to non-EUS version.")

Expand All @@ -546,27 +554,27 @@ def non_eus_to_target_eus_cnv_upgraded(
admin_client,
hco_namespace,
eus_cnv_upgrade_path,
cnv_subscription_scope_session,
cnv_registry_source,
hyperconverged_resource_scope_function,
updated_cnv_subscription_source,
):
version, cnv_image = next(iter(eus_cnv_upgrade_path[EUS].items()))
LOGGER.info(f"Cnv upgrade to version {version} using image: {cnv_image}")
perform_cnv_upgrade(
admin_client=admin_client,
cnv_image_url=cnv_image,
cr_name=hyperconverged_resource_scope_function.name,
hco_namespace=hco_namespace,
cnv_target_version=version.lstrip("v"),
)


@pytest.fixture()
def eus_created_target_hco_csv(admin_client, hco_namespace, eus_hco_target_csv_name):
return get_csv_by_name(
csv_name=eus_hco_target_csv_name,
admin_client=admin_client,
namespace=hco_namespace.name,
)
for version, build_info in sorted(
eus_cnv_upgrade_path[EUS].items(),
key=lambda item: Version(version=item[0]),
):
cnv_image = build_info["cnv_image_url"]
LOGGER.info(f"Cnv upgrade to version {version} using image: {cnv_image}")
perform_cnv_upgrade(
admin_client=admin_client,
cnv_image_url=cnv_image,
cr_name=hyperconverged_resource_scope_function.name,
hco_namespace=hco_namespace,
cnv_target_version=version,
subscription=cnv_subscription_scope_session,
subscription_source=cnv_registry_source["cnv_subscription_source"],
subscription_channel=build_info["channel"],
)
LOGGER.info("Successfully performed cnv upgrades from non-EUS to target EUS version.")


@pytest.fixture()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

LOGGER = logging.getLogger(__name__)

pytestmark = pytest.mark.usefixtures(
"nodes_taints_before_upgrade",
"nodes_labels_before_upgrade",
)


@pytest.mark.product_upgrade_test
@pytest.mark.upgrade
Expand All @@ -20,7 +25,6 @@ def test_eus_upgrade_process(
self,
admin_client,
hco_namespace,
eus_target_cnv_version,
eus_cnv_upgrade_path,
eus_paused_worker_mcp,
eus_paused_workload_update,
Expand All @@ -29,14 +33,14 @@ def test_eus_upgrade_process(
upgraded_odf,
non_eus_to_target_eus_ocp_upgraded,
non_eus_to_target_eus_cnv_upgraded,
eus_created_target_hco_csv,
created_target_hco_csv,
eus_unpaused_workload_update,
eus_unpaused_worker_mcp,
):
LOGGER.info("Validate EUS to EUS upgrade process")
verify_upgrade_cnv(
dyn_client=admin_client,
hco_namespace=hco_namespace,
expected_images=get_related_images_name_and_version(csv=eus_created_target_hco_csv).values(),
expected_images=get_related_images_name_and_version(csv=created_target_hco_csv).values(),
)
LOGGER.info("EUS post upgrade validation completed.")
Loading