diff --git a/src/pybind/mgr/dashboard/ci/cephadm/ceph_cluster.yml b/src/pybind/mgr/dashboard/ci/cephadm/ceph_cluster.yml index 894d5d086ea..bdd84b7f1cd 100755 --- a/src/pybind/mgr/dashboard/ci/cephadm/ceph_cluster.yml +++ b/src/pybind/mgr/dashboard/ci/cephadm/ceph_cluster.yml @@ -12,6 +12,7 @@ parameters: disks: - 15 - 5 + - 5 {% for number in range(0, nodes) %} {{ prefix }}-node-0{{ number }}: diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/create-cluster.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/create-cluster.po.ts index 52be703af28..819afd559b1 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/create-cluster.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/create-cluster.po.ts @@ -24,20 +24,6 @@ export class CreateClusterWizardHelper extends PageHelper { notification.open(); notification.getNotifications().should('contain', 'Cluster expansion skipped by user'); } - - createOSD(deviceType: 'hdd' | 'ssd') { - // Click Primary devices Add button - cy.get('cd-osd-devices-selection-groups[name="Primary"]').as('primaryGroups'); - cy.get('@primaryGroups').find('button').click(); - - // Select all devices with `deviceType` - cy.get('cd-osd-devices-selection-modal').within(() => { - cy.get('.modal-footer .tc_submitButton').as('addButton').should('be.disabled'); - this.filterTable('Type', deviceType); - this.getTableCount('total').should('be.gte', 1); - cy.get('@addButton').click(); - }); - } } export class CreateClusterHostPageHelper extends HostsPageHelper { diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/hosts.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/hosts.po.ts index f2be649ae5f..ffac83ba67b 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/hosts.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/hosts.po.ts @@ -131,7 +131,9 @@ export class HostsPageHelper extends PageHelper { this.getTableCell(this.columnIndex.hostname, hostname).click(); this.clickActionButton('enter-maintenance'); - cy.contains('cd-modal button', 'Continue').click(); + cy.get('cd-modal').within(() => { + cy.contains('button', 'Continue').click(); + }); this.getTableCell(this.columnIndex.hostname, hostname) .parent() @@ -182,7 +184,7 @@ export class HostsPageHelper extends PageHelper { this.clickTab('cd-host-details', hostname, 'Daemons'); cy.get('cd-host-details').within(() => { - cy.wait(10000); + cy.wait(20000); this.expectTableCount('total', 0); }); } diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/osds.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/osds.po.ts index 862c7c6011d..d388a3c5ba6 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/osds.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/osds.po.ts @@ -13,8 +13,7 @@ export class OSDsPageHelper extends PageHelper { status: 5 }; - @PageHelper.restrictTo(pages.create.url) - create(deviceType: 'hdd' | 'ssd') { + create(deviceType: 'hdd' | 'ssd', hostname?: string, expandCluster = false) { // Click Primary devices Add button cy.get('cd-osd-devices-selection-groups[name="Primary"]').as('primaryGroups'); cy.get('@primaryGroups').find('button').click(); @@ -23,15 +22,24 @@ export class OSDsPageHelper extends PageHelper { cy.get('cd-osd-devices-selection-modal').within(() => { cy.get('.modal-footer .tc_submitButton').as('addButton').should('be.disabled'); this.filterTable('Type', deviceType); + if (hostname) { + this.filterTable('Hostname', hostname); + } + + if (expandCluster) { + this.getTableCount('total').should('be.gte', 1); + } cy.get('@addButton').click(); }); - cy.get('@primaryGroups').within(() => { - this.getTableCount('total').as('newOSDCount'); - }); + if (!expandCluster) { + cy.get('@primaryGroups').within(() => { + this.getTableCount('total').as('newOSDCount'); + }); - cy.get(`${pages.create.id} .card-footer .tc_submitButton`).click(); - cy.get(`cd-osd-creation-preview-modal .modal-footer .tc_submitButton`).click(); + cy.get(`${pages.create.id} .card-footer .tc_submitButton`).click(); + cy.get(`cd-osd-creation-preview-modal .modal-footer .tc_submitButton`).click(); + } } @PageHelper.restrictTo(pages.index.url) diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/services.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/services.po.ts index 2d1969b75bd..07bd3b58b8b 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/services.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/cluster/services.po.ts @@ -49,7 +49,7 @@ export class ServicesPageHelper extends PageHelper { case 'ingress': this.selectOption('backend_service', 'rgw.foo'); cy.get('#service_id').should('have.value', 'rgw.foo'); - cy.get('#virtual_ip').type('192.168.20.1/24'); + cy.get('#virtual_ip').type('192.168.100.1/24'); cy.get('#frontend_port').type('8081'); cy.get('#monitor_port').type('8082'); break; @@ -58,6 +58,11 @@ export class ServicesPageHelper extends PageHelper { cy.get('#service_id').type('testnfs'); cy.get('#count').type(count); break; + + default: + cy.get('#service_id').type('test'); + cy.get('#count').type(count); + break; } cy.get('cd-submit-button').click(); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/02-create-cluster-add-host.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/02-create-cluster-add-host.e2e-spec.ts index 0310e473ec2..02b61167de3 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/02-create-cluster-add-host.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/02-create-cluster-add-host.e2e-spec.ts @@ -13,7 +13,7 @@ describe('Create cluster add host page', () => { 'ceph-node-[01-03].cephlab.com' ]; const addHost = (hostname: string, exist?: boolean, pattern?: boolean, labels: string[] = []) => { - cy.get('.btn.btn-accent').first().click({ force: true }); + cy.get('button[data-testid=table-action-button]').click(); createClusterHostPage.add(hostname, exist, false, labels); if (!pattern) { createClusterHostPage.checkExist(hostname, true); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/03-create-cluster-create-services.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/03-create-cluster-create-services.e2e-spec.ts index e1b33fea34f..d52c7d53864 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/03-create-cluster-create-services.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/03-create-cluster-create-services.e2e-spec.ts @@ -7,8 +7,8 @@ describe('Create cluster create services page', () => { const createCluster = new CreateClusterWizardHelper(); const createClusterServicePage = new CreateClusterServicePageHelper(); - const createService = (serviceType: string, serviceName: string, count?: string) => { - cy.get('.btn.btn-accent').first().click({ force: true }); + const createService = (serviceType: string, serviceName: string, count = '1') => { + cy.get('button[data-testid=table-action-button]').click(); createClusterServicePage.addService(serviceType, false, count); createClusterServicePage.checkExist(serviceName, true); }; @@ -28,14 +28,9 @@ describe('Create cluster create services page', () => { describe('when Orchestrator is available', () => { const serviceName = 'rgw.foo'; - it('should create an rgw service', () => { - createService('rgw', serviceName, '2'); - }); - - it('should delete the service and add it back', () => { - createClusterServicePage.deleteService(serviceName); - + it('should create an rgw and mds service', () => { createService('rgw', serviceName, '2'); + createService('mds', 'mds.test'); }); it('should edit a service', () => { @@ -44,8 +39,8 @@ describe('Create cluster create services page', () => { createClusterServicePage.expectPlacementCount(serviceName, daemonCount); }); - it('should create an ingress service', () => { - createService('ingress', 'ingress.rgw.foo', '2'); + it('should delete the mds service', () => { + createClusterServicePage.deleteService('mds.test'); }); }); }); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/04-create-cluster-create-osds.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/04-create-cluster-create-osds.e2e-spec.ts index c8d93b47962..268cf0ad786 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/04-create-cluster-create-osds.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/04-create-cluster-create-osds.e2e-spec.ts @@ -20,21 +20,24 @@ describe('Create cluster create osds page', () => { describe('when Orchestrator is available', () => { it('should create OSDs', () => { - osds.navigateTo(); - osds.getTableCount('total').as('initOSDCount'); + const hostnames = [ + 'ceph-node-00.cephlab.com', + 'ceph-node-02.cephlab.com', + 'ceph-node-03.cephlab.com' + ]; + for (const hostname of hostnames) { + osds.create('hdd', hostname, true); - createCluster.navigateTo(); - createCluster.createCluster(); - cy.get('.nav-link').contains('Create OSDs').click(); - - createCluster.createOSD('hdd'); - - // Go to the Review section and Expand the cluster - // because the drive group spec is only stored - // in frontend and will be lost when refreshed - cy.get('.nav-link').contains('Review').click(); - cy.get('button[aria-label="Next"]').click(); - cy.get('cd-dashboard').should('exist'); + // Go to the Review section and Expand the cluster + // because the drive group spec is only stored + // in frontend and will be lost when refreshed + cy.get('.nav-link').contains('Review').click(); + cy.get('button[aria-label="Next"]').click(); + cy.get('cd-dashboard').should('exist'); + createCluster.navigateTo(); + createCluster.createCluster(); + cy.get('.nav-link').contains('Create OSDs').click(); + } }); }); }); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/06-cluster-check.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/06-cluster-check.e2e-spec.ts index ff6017559f2..531a31b339d 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/06-cluster-check.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/06-cluster-check.e2e-spec.ts @@ -1,6 +1,5 @@ import { CreateClusterWizardHelper } from 'cypress/integration/cluster/create-cluster.po'; import { HostsPageHelper } from 'cypress/integration/cluster/hosts.po'; -import { OSDsPageHelper } from 'cypress/integration/cluster/osds.po'; import { ServicesPageHelper } from 'cypress/integration/cluster/services.po'; describe('when cluster creation is completed', () => { @@ -8,7 +7,6 @@ describe('when cluster creation is completed', () => { const services = new ServicesPageHelper(); const hosts = new HostsPageHelper(); - const serviceName = 'rgw.foo'; const hostnames = [ 'ceph-node-00.cephlab.com', 'ceph-node-01.cephlab.com', @@ -64,51 +62,4 @@ describe('when cluster creation is completed', () => { } }); }); - - describe('OSDs page', () => { - const osds = new OSDsPageHelper(); - - beforeEach(() => { - osds.navigateTo(); - }); - - it('should check if osds are created', { retries: 1 }, () => { - osds.getTableCount('total').should('be.gte', 2); - }); - }); - - describe('Services page', () => { - beforeEach(() => { - services.navigateTo(); - }); - - it('should check if services are created', () => { - services.checkExist(serviceName, true); - }); - }); - - describe('Host actions', () => { - beforeEach(() => { - hosts.navigateTo(); - }); - - it('should check if rgw daemon is running', () => { - hosts.clickTab('cd-host-details', hostnames[3], 'Daemons'); - cy.get('cd-host-details').within(() => { - services.checkServiceStatus('rgw'); - }); - }); - - it('should force maintenance and exit', { retries: 1 }, () => { - hosts.maintenance(hostnames[3], true, true); - }); - - it('should drain, remove and add the host back', () => { - hosts.drain(hostnames[1]); - hosts.remove(hostnames[1]); - hosts.navigateTo('add'); - hosts.add(hostnames[1]); - hosts.checkExist(hostnames[1], true); - }); - }); }); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/07-osds.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/07-osds.e2e-spec.ts new file mode 100644 index 00000000000..90db14668f7 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/07-osds.e2e-spec.ts @@ -0,0 +1,22 @@ +import { OSDsPageHelper } from 'cypress/integration/cluster/osds.po'; + +describe('OSDs page', () => { + const osds = new OSDsPageHelper(); + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + osds.navigateTo(); + }); + + it('should check if atleast 3 osds are created', { retries: 3 }, () => { + // we have created a total of more than 3 osds throughout + // the whole tests so ensuring that atleast + // 3 osds are listed in the table. Since the OSD + // creation can take more time going with + // retry of 3 + for (let id = 0; id < 3; id++) { + osds.checkStatus(id, ['in', 'up']); + } + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/08-hosts.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/08-hosts.e2e-spec.ts new file mode 100644 index 00000000000..942321542b8 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/08-hosts.e2e-spec.ts @@ -0,0 +1,42 @@ +import { HostsPageHelper } from 'cypress/integration/cluster/hosts.po'; +import { ServicesPageHelper } from 'cypress/integration/cluster/services.po'; + +describe('Host Page', () => { + const hosts = new HostsPageHelper(); + const services = new ServicesPageHelper(); + + const hostnames = [ + 'ceph-node-00.cephlab.com', + 'ceph-node-01.cephlab.com', + 'ceph-node-02.cephlab.com', + 'ceph-node-03.cephlab.com' + ]; + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + hosts.navigateTo(); + }); + + // rgw is needed for testing the force maintenance + it('should check if rgw daemon is running on all hosts', () => { + for (const hostname of hostnames) { + hosts.clickTab('cd-host-details', hostname, 'Daemons'); + cy.get('cd-host-details').within(() => { + services.checkServiceStatus('rgw'); + }); + } + }); + + it('should force maintenance and exit', { retries: 2 }, () => { + hosts.maintenance(hostnames[1], true, true); + }); + + it('should drain, remove and add the host back', () => { + hosts.drain(hostnames[1]); + hosts.remove(hostnames[1]); + hosts.navigateTo('add'); + hosts.add(hostnames[1]); + hosts.checkExist(hostnames[1], true); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/09-services.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/09-services.e2e-spec.ts new file mode 100644 index 00000000000..9b49c75aca6 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/09-services.e2e-spec.ts @@ -0,0 +1,27 @@ +import { ServicesPageHelper } from 'cypress/integration/cluster/services.po'; + +describe('Services page', () => { + const services = new ServicesPageHelper(); + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + services.navigateTo(); + }); + + it('should check if rgw service is created', () => { + services.checkExist('rgw.foo', true); + }); + + it('should create and delete an mds service', () => { + services.navigateTo('create'); + services.addService('mds', false); + services.checkExist('mds.test', true); + + services.clickServiceTab('mds.test', 'Details'); + cy.get('cd-service-details').within(() => { + services.checkServiceStatus('mds'); + }); + + services.deleteService('mds.test'); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/07-nfs-exports.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/10-nfs-exports.e2e-spec.ts similarity index 100% rename from src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/07-nfs-exports.e2e-spec.ts rename to src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/10-nfs-exports.e2e-spec.ts diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html index b60c9b1ddb4..9896d56206d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.html @@ -6,6 +6,7 @@ [ngClass]="{'disabled': disableSelectionAction(currentAction)}" (click)="useClickAction(currentAction)" [routerLink]="useRouterLink(currentAction)" + data-testid="table-action-button" [preserveFragment]="currentAction.preserveFragment ? '' : null"> {{ currentAction.name }}