From 477aa254fd233fcc0f8db90b06a0c54e27122299 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Thu, 16 Jul 2026 14:05:48 -0400 Subject: [PATCH] UPSTREAM: : test: add allow-case for operator maxOCPVersion > cluster version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a second ReleaseGate-eligible OTE test verifying that an operator whose olm.maxOpenShiftVersion exceeds the current cluster version does not block cluster upgrade (InstalledOLMOperatorsUpgradeable stays True). The existing test only covered the blocking path (maxOCPVersion == current version → False). This covers the complementary allow path (maxOCPVersion == next minor → True), directly exercising the normalization logic introduced for the 4.23/5.0 co-release boundary. A nextMinorVersion() helper mirrors the 4.23→5.1 special case so the bundle annotation is always set to the correct next upgrade target. Run 'make build-update' to register the new allow-case test in the extension metadata after adding it to olmv1-incompatible.go. Co-Authored-By: Claude Sonnet 4.6 (1M context) Signed-off-by: Todd Short --- .../openshift_payload_olmv1.json | 10 ++++ .../test/olmv1-incompatible.go | 56 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json b/openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json index 6229899069..acb50da217 100644 --- a/openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json +++ b/openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json @@ -1497,6 +1497,16 @@ "lifecycle": "blocking", "environmentSelector": {} }, + { + "name": "[sig-olmv1][OCPFeatureGate:NewOLM] OLMv1 operator installation should not block cluster upgrades if the operator's maxOCPVersion exceeds the current cluster version", + "labels": {}, + "resources": { + "isolation": {} + }, + "source": "openshift:payload:olmv1", + "lifecycle": "blocking", + "environmentSelector": {} + }, { "name": "[sig-olmv1][OCPFeatureGate:NewOLMPreflightPermissionChecks][Skipped:Disconnected] OLMv1 operator preflight checks should report error when {services} are not specified", "labels": {}, diff --git a/openshift/tests-extension/test/olmv1-incompatible.go b/openshift/tests-extension/test/olmv1-incompatible.go index c816b9a2fb..7abf5cfb4a 100644 --- a/openshift/tests-extension/test/olmv1-incompatible.go +++ b/openshift/tests-extension/test/olmv1-incompatible.go @@ -2,6 +2,7 @@ package test import ( "context" + "fmt" //nolint:staticcheck // ST1001: dot-imports for readability . "github.com/onsi/ginkgo/v2" @@ -63,6 +64,61 @@ var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM] OLMv1 operator installation }) }) +// nextMinorVersion returns the next OCP minor version after the current cluster version. +// OCP 4.23 and 5.0 are co-released equivalents whose only upgrade target is 5.1, so +// a cluster at 4.23 returns "5.1" rather than the naive "4.24". +func nextMinorVersion() string { + v := env.Get().OpenShiftVersion // "MAJOR.MINOR", e.g. "5.0" + var major, minor int + if _, err := fmt.Sscanf(v, "%d.%d", &major, &minor); err != nil { + Fail(fmt.Sprintf("failed to parse OpenShift version %q: %v", v, err)) + } + if major == 4 && minor == 23 { + return "5.1" + } + return fmt.Sprintf("%d.%d", major, minor+1) +} + +var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM] OLMv1 operator installation", func() { + var unique, nsName, ccName, opName string + BeforeEach(func(ctx SpecContext) { + replacements := map[string]string{ + "{{ TEST-BUNDLE }}": "", // Auto-filled + "{{ NAMESPACE }}": "", // Auto-filled + "{{ VERSION }}": nextMinorVersion(), + + // Using the shell image provided by origin as the controller image. + // The image is mirrored into disconnected environments for testing. + "{{ TEST-CONTROLLER }}": image.ShellImage(), + } + unique, nsName, ccName, opName = helpers.NewCatalogAndClusterBundles(ctx, replacements, + catalogdata.AssetNames, catalogdata.Asset, + operatordata.AssetNames, operatordata.Asset, + ) + }) + + AfterEach(func(ctx SpecContext) { + if CurrentSpecReport().Failed() { + By("dumping for debugging") + helpers.DescribeAllClusterCatalogs(context.Background()) + helpers.DescribeAllClusterExtensions(context.Background(), nsName) + } + }) + + It("should not block cluster upgrades if the operator's maxOCPVersion exceeds the current cluster version", func(ctx SpecContext) { + By("waiting for InstalledOLMOperatorUpgradable to be true") + waitForOlmUpgradeStatus(ctx, operatorv1.ConditionTrue, "") + + By("creating the ClusterExtension") + ceName, ceCleanup := helpers.CreateClusterExtension(opName, "", nsName, unique, helpers.WithCatalogNameSelector(ccName)) + DeferCleanup(ceCleanup) + helpers.ExpectClusterExtensionToBeInstalled(ctx, ceName) + + By("verifying InstalledOLMOperatorUpgradable remains true after installing the operator") + waitForOlmUpgradeStatus(ctx, operatorv1.ConditionTrue, "") + }) +}) + func waitForOlmUpgradeStatus(ctx SpecContext, status operatorv1.ConditionStatus, name string) { const reasonIncompatibleOperatorsInstalled = "IncompatibleOperatorsInstalled" const typeInstalledOLMOperatorsUpgradeable = "InstalledOLMOperatorsUpgradeable"