From 8478a7c9077ac93941ada4a180688481fa6c5d68 Mon Sep 17 00:00:00 2001 From: David Rajnoha Date: Mon, 8 Jun 2026 10:53:21 +0200 Subject: [PATCH 1/2] fix: add --install-mode=AllNamespaces to operator-sdk run bundle COO's CSV only supports AllNamespaces (all other install modes are false). Without the flag, OLM defaults to OwnNamespace which COO rejects, causing the install to time out at 10m. Co-authored-by: Cursor --- web/cypress/support/commands/coo-install-commands.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/cypress/support/commands/coo-install-commands.ts b/web/cypress/support/commands/coo-install-commands.ts index 578c9f81e..127f15a5e 100644 --- a/web/cypress/support/commands/coo-install-commands.ts +++ b/web/cypress/support/commands/coo-install-commands.ts @@ -48,7 +48,7 @@ export const cooInstallUtils = { )}`, ); cy.exec( - `operator-sdk run bundle --timeout=10m --namespace ${ + `operator-sdk run bundle --timeout=10m --install-mode=AllNamespaces --namespace ${ MCP.namespace } --security-context-config restricted ${Cypress.env( 'KONFLUX_COO_BUNDLE_IMAGE', @@ -78,7 +78,7 @@ export const cooInstallUtils = { )}`, ); cy.exec( - `operator-sdk run bundle --timeout=10m --namespace ${ + `operator-sdk run bundle --timeout=10m --install-mode=AllNamespaces --namespace ${ MCP.namespace } --security-context-config restricted ${Cypress.env( 'CUSTOM_COO_BUNDLE_IMAGE', From a7f4dcf3828fa452f902cfaf815f78565c244f16 Mon Sep 17 00:00:00 2001 From: David Rajnoha Date: Wed, 10 Jun 2026 15:07:24 +0200 Subject: [PATCH 2/2] fix: enable OpenShift mode for bundle-installed COO Add enableOpenShiftMode to the setupCOO flow for bundle installs (KONFLUX_COO_BUNDLE_IMAGE / CUSTOM_COO_BUNDLE_IMAGE). The operator-sdk bundle does not include --openshift.enabled=true by default, so the operator's UIPlugin controller and Console registration remain disabled. Key fixes: - Dynamically find the observability-operator deployment index in the CSV (previously hardcoded to index 0 which was obo-prometheus-operator) - Patch both the CSV and the live deployment to ensure persistence across OLM reconciliation triggered by subsequent image patches - Add operator-sdk cleanup with correct package name (observability-operator) to cleanupCOONamespace to prevent "error creating catalog" on re-install - Increase waitForPodsDeleted timeout to 300s for namespace cleanup Co-authored-by: Cursor --- .../support/commands/coo-install-commands.ts | 123 +++++++++++++++++- .../support/commands/operator-commands.ts | 6 + 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/web/cypress/support/commands/coo-install-commands.ts b/web/cypress/support/commands/coo-install-commands.ts index 127f15a5e..39873b2a2 100644 --- a/web/cypress/support/commands/coo-install-commands.ts +++ b/web/cypress/support/commands/coo-install-commands.ts @@ -65,11 +65,13 @@ export const cooInstallUtils = { 'KUBECONFIG_PATH', )} apply -f ./cypress/fixtures/coo/coo-imagecontentsourcepolicy.yaml`, ); + cy.log(`Creating namespace ${MCP.namespace}`); cy.exec( `oc create namespace ${MCP.namespace} --kubeconfig ${Cypress.env( 'KUBECONFIG_PATH', )} --dry-run=client -o yaml | oc apply --kubeconfig ${Cypress.env('KUBECONFIG_PATH')} -f -`, ); + cy.log(`Labeling namespace ${MCP.namespace} with openshift.io/cluster-monitoring=true`); cy.exec( `oc label namespace ${ MCP.namespace @@ -162,6 +164,107 @@ export const cooInstallUtils = { } }, + enableOpenShiftMode(MCP: { namespace: string }): void { + if (!Cypress.env('KONFLUX_COO_BUNDLE_IMAGE') && !Cypress.env('CUSTOM_COO_BUNDLE_IMAGE')) { + return; + } + + const kubeconfig = Cypress.env('KUBECONFIG_PATH'); + const ns = MCP.namespace; + cy.log('Enabling OpenShift mode on bundle-installed COO'); + + // Patch the CSV so OLM's source of truth includes the flag. + // Find the correct CSV and deployment index for observability-operator. + cy.exec( + `oc get csv -n ${ns} -o jsonpath=` + + `'{range .items[?(@.status.phase=="Succeeded")]}` + + `{.metadata.name}{"\\n"}{end}' --kubeconfig ${kubeconfig}`, + ).then((result) => { + const csvNames = result.stdout.trim().split('\n').filter(Boolean); + const csvName = csvNames.find((name) => name.includes('observability-operator')); + if (!csvName) { + throw new Error( + `No observability-operator CSV found in namespace ${ns}. ` + + `Available CSVs: [${csvNames.join(', ')}]`, + ); + } + cy.log(`Found CSV: ${csvName}`); + + cy.exec( + `oc get csv ${csvName} -n ${ns} -o jsonpath=` + + `'{range .spec.install.spec.deployments[*]}` + + `{.name}{"\\n"}{end}' --kubeconfig ${kubeconfig}`, + ).then((deploymentsResult) => { + const deploymentNames = deploymentsResult.stdout.trim().split('\n').filter(Boolean); + const opIdx = deploymentNames.indexOf('observability-operator'); + if (opIdx === -1) { + throw new Error( + `observability-operator not found in CSV deployments: [${deploymentNames.join(', ')}]`, + ); + } + cy.log(`Patching CSV ${csvName} deployment[${opIdx}] to add --openshift.enabled=true`); + cy.exec( + `oc patch csv ${csvName} -n ${ns} --type=json ` + + `-p '[{"op":"add","path":"/spec/install/spec/deployments/` + + `${opIdx}/spec/template/spec/containers/0/args/-",` + + `"value":"--openshift.enabled=true"}]' ` + + `--kubeconfig ${kubeconfig}`, + ); + }); + }); + + // Step 2: Patch the deployment directly to apply the change immediately. + cy.log('Patching deployment to add --openshift.enabled=true'); + cy.exec( + `oc patch deployment observability-operator -n ${ns} --type=json ` + + `-p '[{"op":"add","path":"/spec/template/spec/containers/0/args/-",` + + `"value":"--openshift.enabled=true"}]' ` + + `--kubeconfig ${kubeconfig}`, + ); + + // Step 3: Wait for the rollout to complete. + cy.exec( + `oc rollout status deployment/observability-operator -n ${ns} ` + + `--timeout=120s --kubeconfig ${kubeconfig}`, + { timeout: 130000 }, + ); + + // Final verification: confirm the running pod actually has the flag. + cy.exec( + `oc get deployment observability-operator -n ${ns} ` + + `-o jsonpath="{.spec.template.spec.containers[0].args}" --kubeconfig ${kubeconfig}`, + ).then((result) => { + const args = result.stdout; + cy.log(`Deployment args after rollout: ${args}`); + if (!args.includes('openshift.enabled=true')) { + cy.exec(`oc get csv -n ${ns} -o yaml --kubeconfig ${kubeconfig}`, { + failOnNonZeroExit: false, + }).then((csvResult) => { + cy.log(`CSV YAML:\n${csvResult.stdout.substring(0, 3000)}`); + }); + cy.exec( + `oc get deployment observability-operator -n ${ns} -o yaml --kubeconfig ${kubeconfig}`, + ).then((yamlResult) => { + cy.log(`Deployment YAML:\n${yamlResult.stdout}`); + }); + cy.then(() => { + throw new Error( + '--openshift.enabled=true NOT found in deployment args after rollout. ' + + `Actual args: ${args}`, + ); + }); + } + }); + + cy.exec( + `oc logs -l app.kubernetes.io/name=observability-operator -n ${ns} ` + + `--tail=5 --kubeconfig ${kubeconfig}`, + { failOnNonZeroExit: false }, + ).then((result) => { + cy.log(`Operator logs after restart:\n${result.stdout}`); + }); + }, + cleanupCOONamespace(MCP: { namespace: string }): void { if (Cypress.env('SKIP_COO_INSTALL')) { return; @@ -169,6 +272,24 @@ export const cooInstallUtils = { cy.log('Remove Cluster Observability Operator namespace'); + // For bundle installs, run operator-sdk cleanup first to remove + // CatalogSource, registry pod, and other bundle-specific resources. + // The bundle package name is "observability-operator" (not the MCP.packageName + // which is "cluster-observability-operator" used for catalog installs). + if (Cypress.env('KONFLUX_COO_BUNDLE_IMAGE') || Cypress.env('CUSTOM_COO_BUNDLE_IMAGE')) { + cy.exec( + `operator-sdk cleanup observability-operator -n ${MCP.namespace} ` + + `--kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, + { failOnNonZeroExit: false, timeout: 60000 }, + ).then((result) => { + if (result.code === 0) { + cy.log('operator-sdk cleanup completed successfully'); + } else { + cy.log(`operator-sdk cleanup failed (may not exist): ${result.stderr}`); + } + }); + } + cy.exec(`oc get namespace ${MCP.namespace} --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`, { timeout: readyTimeoutMilliseconds, failOnNonZeroExit: false, @@ -287,7 +408,7 @@ export const cooInstallUtils = { checkStatus(); cy.then(() => { - cooInstallUtils.waitForPodsDeleted(MCP.namespace); + cooInstallUtils.waitForPodsDeleted(MCP.namespace, 300000); }); } else { cy.log('Namespace does not exist, skipping deletion'); diff --git a/web/cypress/support/commands/operator-commands.ts b/web/cypress/support/commands/operator-commands.ts index 12ae5e72c..b19086d15 100644 --- a/web/cypress/support/commands/operator-commands.ts +++ b/web/cypress/support/commands/operator-commands.ts @@ -67,6 +67,11 @@ function collectDebugInfo(MP: { namespace: string }, MCP?: { namespace: string } cy.log('DEBUG not set. Skipping operator debug information collection.'); return; } + // TODO: Remove once DataViewFilters incompatibility with COO 1.5.0 is resolved + if (Cypress.env('COO_1_5_0')) { + cy.log('COO_1_5_0 set: skipping collectDebugInfo (DataViewFilters incompatibility)'); + return; + } cy.aboutModal(); cy.podImage('monitoring-plugin', MP.namespace); if (MCP && MCP.namespace) { @@ -234,6 +239,7 @@ Cypress.Commands.add( } cooInstallUtils.installCOO(MCP); cooInstallUtils.waitForCOOReady(MCP); + cooInstallUtils.enableOpenShiftMode(MCP); imagePatchUtils.setupMonitoringConsolePlugin(MCP); if (opts.healthAnalyzer) { imagePatchUtils.setupClusterHealthAnalyzer(MCP);