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
10 changes: 6 additions & 4 deletions devspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ dev:
sync:
- path: ./web/dist:/opt/app-root/web/dist
startContainer: true
command: ["make"]
args: ["start-devspace-backend"]
command: ["sh", "-c"]
args:
- until test -f /opt/app-root/web/dist/plugin-manifest.json; do sleep 1; done; exec make start-devspace-backend
ssh:
enabled: true

Expand All @@ -63,7 +64,8 @@ dev:
sync:
- path: ./web/dist:/opt/app-root/web/dist
startContainer: true
command: ["make"]
args: ["start-devspace-mcp-backend"]
command: ["sh", "-c"]
args:
- until test -f /opt/app-root/web/dist/plugin-manifest.json; do sleep 1; done; exec make start-devspace-mcp-backend
ssh:
enabled: true
2 changes: 1 addition & 1 deletion scripts/build-image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ echo_vars

if [[ $INTERACTIVE == 1 ]]; then
# Prompt use it check env vars before proceeding to build
read -r -p "Are the environmental variables correct [y/N] " response
read -r -p "Are the environmental variables correct [Y/n] " response
if [[ "${response:0:1}" =~ ^([nN])$ ]]; then
exit 0
fi
Expand Down
144 changes: 32 additions & 112 deletions web/cypress/support/commands/coo-install-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,127 +355,47 @@ export const cooInstallUtils = {
}
});

const checkIntervalMs = 15000;
const startTime = Date.now();
const maxWaitTimeMs = 600000;

const checkStatus = () => {
const elapsed = Date.now() - startTime;

if (elapsed > maxWaitTimeMs) {
cy.log(
`${elapsed}ms - Timeout reached (${maxWaitTimeMs / 60000}m). Namespace ${
CLUSTER_OBSERVABILITY_OPERATOR.namespace
} still terminating. Attempting force-delete.`,
);
return cy
cy.waitUntil<boolean>(
() =>
cy
.exec(
`./cypress/fixtures/coo/force_delete_ns.sh ` +
`${CLUSTER_OBSERVABILITY_OPERATOR.namespace} "${Cypress.env('KUBECONFIG_PATH')}"`,
{ failOnNonZeroExit: false, timeout: installTimeoutMilliseconds },
`oc get namespace ${CLUSTER_OBSERVABILITY_OPERATOR.namespace}` +
` --kubeconfig "${Cypress.env('KUBECONFIG_PATH')}"`,
{ failOnNonZeroExit: false },
)
.then((result) => {
cy.log(`${elapsed}ms - Force delete output: ${result.stdout}`);
if (result.code !== 0) {
cy.log(`Force delete failed with exit code ${result.code}: ${result.stderr}`);
Cypress.log({
name: 'cleanupCOONamespace',
message: `${CLUSTER_OBSERVABILITY_OPERATOR.namespace} is successfully deleted.`,
});
return cy.wrap(true, { log: false });
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
});
}

cy.exec(
`oc get ns ${CLUSTER_OBSERVABILITY_OPERATOR.namespace} --kubeconfig "${Cypress.env(
'KUBECONFIG_PATH',
)}" -o jsonpath='{.status.phase}'`,
{ failOnNonZeroExit: false },
).then((result) => {
if (result.code !== 0) {
cy.log(
`${elapsed}ms - ${CLUSTER_OBSERVABILITY_OPERATOR.namespace} is ` +
`successfully deleted.`,
);
return;
}
const status = result.stdout.trim();

if (status === 'Terminating') {
cy.log(
`${elapsed}ms - ${CLUSTER_OBSERVABILITY_OPERATOR.namespace} is still ` +
`'Terminating'. Retrying in ${
checkIntervalMs / 1000
}s. Elapsed: ${Math.round(elapsed / 1000)}s`,
);
cy.exec(
`./cypress/fixtures/coo/force_delete_ns.sh ` +
`${CLUSTER_OBSERVABILITY_OPERATOR.namespace} "${Cypress.env('KUBECONFIG_PATH')}"`,
{ failOnNonZeroExit: false, timeout: installTimeoutMilliseconds },
).then((forceResult) => {
cy.log(`${elapsed}ms - Force delete output: ${forceResult.stdout}`);
if (forceResult.code !== 0) {
cy.log(
`Force delete failed with exit code ${forceResult.code}: ${forceResult.stderr}`,
);
}
});
cy.wait(checkIntervalMs).then(checkStatus);
} else {
cy.log(
`${elapsed}ms - ${CLUSTER_OBSERVABILITY_OPERATOR.namespace} changed to ` +
`unexpected state: ${status}. Stopping monitoring.`,
);
}
});
};

checkStatus();

cy.then(() => {
cooInstallUtils.waitForPodsDeleted(CLUSTER_OBSERVABILITY_OPERATOR.namespace, 300000);
});
return cy
.exec(
`./cypress/fixtures/coo/force_delete_ns.sh ${
CLUSTER_OBSERVABILITY_OPERATOR.namespace
} "${Cypress.env('KUBECONFIG_PATH')}"`,
{ failOnNonZeroExit: false, timeout: installTimeoutMilliseconds },
)
.then((forceResult) => {
Cypress.log({
name: 'cleanupCOONamespace',
message: `Force delete output: ${forceResult.stdout}`,
});
return false;
});
}),
{
timeout: 600000,
interval: 15000,
errorMsg: `Timed out deleting namespace ${CLUSTER_OBSERVABILITY_OPERATOR.namespace}`,
},
);
} else {
cy.log('Namespace does not exist, skipping deletion');
}
});
},

waitForPodsDeleted(namespace: string, maxWaitMs: number = 120000): void {
const kubeconfigPath = Cypress.env('KUBECONFIG_PATH') as string;
const checkIntervalMs = 5000;
const startTime = Date.now();
const podPatterns = 'monitoring|perses|perses-0|health-analyzer|troubleshooting-panel|korrel8r';

const checkPods = () => {
const elapsed = Date.now() - startTime;

if (elapsed > maxWaitMs) {
throw new Error(`Timeout: Pods still exist after ${maxWaitMs / 1000}s`);
}

cy.exec(`oc get pods -n ${namespace} --kubeconfig ${kubeconfigPath} -o name`, {
failOnNonZeroExit: false,
}).then((result) => {
if (result.code !== 0) {
if (result.stderr.includes('not found')) {
cy.log(`All target pods deleted after ${elapsed}ms (namespace gone)`);
} else {
cy.log(`${elapsed}ms - oc get pods failed: ${result.stderr}, retrying...`);
cy.wait(checkIntervalMs).then(checkPods);
}
return;
}

const matchingPods = result.stdout
.split('\n')
.filter((line) => new RegExp(podPatterns).test(line));

if (matchingPods.length === 0) {
cy.log(`All target pods deleted after ${elapsed}ms`);
} else {
cy.log(`${elapsed}ms - ${matchingPods.length} pod(s) still exist, retrying...`);
cy.wait(checkIntervalMs).then(checkPods);
}
});
};

checkPods();
},
};
28 changes: 18 additions & 10 deletions web/cypress/support/perses/99.coo_rbac_perses_user1.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,14 @@ export function testCOORBACPersesTestsDevUser1(
listPersesDashboardsPage.assertCreateButtonIsEnabled();
listPersesDashboardsPage.clickCreateButton();
persesCreateDashboardsPage.createDashboardShouldBeLoaded();
persesCreateDashboardsPage.assertProjectNotExistsInDropdown('observ-test');
// Non-viewable projects are absent from the dropdown.
persesCreateDashboardsPage.assertProjectNotExistsInDropdown('perses-dev');
persesCreateDashboardsPage.assertProjectNotExistsInDropdown('openshift-monitoring');
persesCreateDashboardsPage.assertProjectNotExistsInDropdown('empty-namespace3');
persesCreateDashboardsPage.assertProjectNotExistsInDropdown('empty-namespace4');
// Viewable but non-creatable projects are listed but creation is denied.
persesCreateDashboardsPage.assertCreateAccessDenied('observ-test');
persesCreateDashboardsPage.assertCreateAccessDenied('openshift-monitoring');
// Editable project is selectable and creatable.
persesCreateDashboardsPage.assertProjectDropdown('openshift-cluster-observability-operator');
persesCreateDashboardsPage.createDashboardDialogCancelButton();

Expand Down Expand Up @@ -428,11 +431,11 @@ export function testCOORBACPersesTestsDevUser1(
cy.log(`6.2. Change namespace to observ-test`);
cy.changeNamespace('observ-test');

cy.log(`6.3. Assert Kebab icon is disabled`);
cy.log(`6.3. Assert Rename/Delete row actions are disabled`);
listPersesDashboardsPage.filter.byName(
persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0],
);
listPersesDashboardsPage.assertKebabIconDisabled();
listPersesDashboardsPage.assertKebabRowActionsDisabled();

cy.log(`6.4. Change namespace to openshift-cluster-observability-operator`);
cy.changeNamespace('openshift-cluster-observability-operator');
Expand All @@ -458,8 +461,7 @@ export function testCOORBACPersesTestsDevUser1(
persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0],
);
listPersesDashboardsPage.countDashboards('1');
listPersesDashboardsPage.clickKebabIcon();
listPersesDashboardsPage.assertKebabIconDisabled();
listPersesDashboardsPage.assertKebabRowActionsDisabled();
listPersesDashboardsPage.clearAllFilters();

cy.log(`6.8. Filter by Project and Name`);
Expand Down Expand Up @@ -562,11 +564,14 @@ export function testCOORBACPersesTestsDevUser1(
listPersesDashboardsPage.clickDuplicateOption();

cy.log(`8.5. Assert project dropdown options`);
listPersesDashboardsPage.assertDuplicateProjectDropdownNotExists('observ-test');
// Non-viewable projects are absent from the dropdown.
listPersesDashboardsPage.assertDuplicateProjectDropdownNotExists('perses-dev');
listPersesDashboardsPage.assertDuplicateProjectDropdownNotExists('empty-namespace3');
listPersesDashboardsPage.assertDuplicateProjectDropdownNotExists('empty-namespace4');
listPersesDashboardsPage.assertDuplicateProjectDropdownNotExists('openshift-monitoring');
// Viewable but non-creatable projects are listed but duplication is denied.
listPersesDashboardsPage.assertDuplicateProjectDenied('observ-test');
listPersesDashboardsPage.assertDuplicateProjectDenied('openshift-monitoring');
// Editable project is selectable and creatable.
listPersesDashboardsPage.assertDuplicateProjectDropdownExists(
'openshift-cluster-observability-operator',
);
Expand Down Expand Up @@ -642,11 +647,14 @@ export function testCOORBACPersesTestsDevUser1(
persesImportDashboardsPage.assertPersesDashboardDetected();

cy.log(`10.4. Verify project dropdown options`);
persesImportDashboardsPage.assertProjectNotExistsInDropdown('observ-test');
// Non-viewable projects are absent from the dropdown.
persesImportDashboardsPage.assertProjectNotExistsInDropdown('perses-dev');
persesImportDashboardsPage.assertProjectNotExistsInDropdown('openshift-monitoring');
persesImportDashboardsPage.assertProjectNotExistsInDropdown('empty-namespace3');
persesImportDashboardsPage.assertProjectNotExistsInDropdown('empty-namespace4');
// Viewable but non-creatable projects are listed but import is denied.
persesImportDashboardsPage.assertImportAccessDenied('observ-test');
persesImportDashboardsPage.assertImportAccessDenied('openshift-monitoring');
// Editable project is selectable and creatable.
persesImportDashboardsPage.assertProjectDropdown('openshift-cluster-observability-operator');
persesImportDashboardsPage.clickCancelButton();

Expand Down
59 changes: 31 additions & 28 deletions web/cypress/support/perses/99.coo_rbac_perses_user2.cy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { persesDashboardsPage } from '../../views/perses-dashboards';
import { listPersesDashboardsPage } from '../../views/perses-dashboards-list-dashboards';
import { persesCreateDashboardsPage } from '../../views/perses-dashboards-create-dashboard';
import { persesImportDashboardsPage } from '../../views/perses-dashboards-import-dashboard';
import {
persesDashboardsDashboardDropdownCOO,
persesDashboardsDashboardDropdownPersesDev,
Expand Down Expand Up @@ -114,67 +116,68 @@ export function testCOORBACPersesTestsDevUser2(
persesDashboardsPage.assertEditButtonIsDisabled();
});

it(`3.${perspectiveName} perspective - Create button validation - Disabled`, () => {
it(`3.${perspectiveName} perspective - Create button validation - Access denied`, () => {
cy.log(`3.1. use sidebar nav to go to Observe > Dashboards (Perses)`);
listPersesDashboardsPage.shouldBeLoaded(dashboardsPageName);

cy.log(`3.2. Verify Create button is disabled`);
listPersesDashboardsPage.assertCreateButtonIsDisabled();

cy.log(`3.3 change namespace to perses-dev`);
cy.log(`3.2 change namespace to perses-dev`);
cy.changeNamespace('perses-dev');

cy.log(`3.4. Verify Create button is disabled`);
listPersesDashboardsPage.assertCreateButtonIsDisabled();

cy.log(`3.5. Change namespace to openshift-monitoring`);
cy.changeNamespace('openshift-monitoring');
listPersesDashboardsPage.assertCreateButtonIsDisabled();
cy.log(`3.3. Verify Create button is enabled but creation is denied for perses-dev`);
listPersesDashboardsPage.assertCreateButtonIsEnabled();
listPersesDashboardsPage.clickCreateButton();
persesCreateDashboardsPage.createDashboardShouldBeLoaded();
persesCreateDashboardsPage.assertCreateAccessDenied('perses-dev');
persesCreateDashboardsPage.assertCreateAccessDenied('openshift-monitoring');
persesCreateDashboardsPage.createDashboardDialogCancelButton();
});

it(`4.${perspectiveName} perspective - Kebab icon - Disabled`, () => {
it(`4.${perspectiveName} perspective - Kebab icon - Row actions denied`, () => {
cy.log(`4.1. use sidebar nav to go to Observe > Dashboards (Perses)`);
listPersesDashboardsPage.shouldBeLoaded(dashboardsPageName);

cy.log(`4.2. Change namespace to perses-dev`);
cy.changeNamespace('perses-dev');

cy.log(`4.3. Assert Kebab icon is disabled`);
cy.log(`4.3. Assert Rename/Delete row actions are disabled`);
listPersesDashboardsPage.filter.byName(
persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0],
);
listPersesDashboardsPage.assertKebabIconDisabled();
listPersesDashboardsPage.assertKebabRowActionsDisabled();

cy.log(`4.4. Assert Duplicate is blocked by access-denied in the modal`);
listPersesDashboardsPage.assertDuplicateAccessDenied('perses-dev');
listPersesDashboardsPage.clearAllFilters();

cy.log(`4.4. Change namespace to All Projects`);
cy.log(`4.5. Change namespace to All Projects`);
cy.changeNamespace('All Projects');

cy.log(`4.5. Assert Kebab icon is disabled`);
cy.log(`4.6. Assert Rename/Delete row actions are disabled`);
listPersesDashboardsPage.filter.byProject('perses-dev');
listPersesDashboardsPage.filter.byName(
persesDashboardsDashboardDropdownPersesDev.PERSES_DASHBOARD_SAMPLE[0],
);
listPersesDashboardsPage.countDashboards('1');
listPersesDashboardsPage.assertKebabIconDisabled();
listPersesDashboardsPage.assertKebabRowActionsDisabled();
listPersesDashboardsPage.clearAllFilters();
});

it(`5.${perspectiveName} perspective - Import button validation - Disabled`, () => {
it(`5.${perspectiveName} perspective - Import button validation - Access denied`, () => {
cy.log(`5.1. use sidebar nav to go to Observe > Dashboards (Perses)`);
listPersesDashboardsPage.shouldBeLoaded(dashboardsPageName);

cy.log(`5.2. Change namespace to perses-dev`);
cy.changeNamespace('perses-dev');

cy.log(`5.3. Verify Import button is disabled`);
listPersesDashboardsPage.assertImportButtonIsDisabled();

cy.log(`5.5. Change namespace to openshift-monitoring`);
cy.changeNamespace('openshift-monitoring');
listPersesDashboardsPage.assertImportButtonIsDisabled();

cy.log(`5.6. Change namespace to All Projects`);
cy.changeNamespace('All Projects');
listPersesDashboardsPage.assertImportButtonIsDisabled();
cy.log(`5.3. Verify Import button is enabled but import is denied for perses-dev`);
listPersesDashboardsPage.assertImportButtonIsEnabled();
listPersesDashboardsPage.clickImportButton();
persesImportDashboardsPage.importDashboardShouldBeLoaded();
persesImportDashboardsPage.uploadFile(
'./cypress/fixtures/coo/coo140_perses/import/testing-perses-dashboard.json',
);
persesImportDashboardsPage.assertPersesDashboardDetected();
persesImportDashboardsPage.assertImportAccessDenied('perses-dev');
persesImportDashboardsPage.clickCancelButton();
});
}
Loading