From b6759b75c9fc4d3fb565201aa6bbe0c2473fd3d4 Mon Sep 17 00:00:00 2001 From: Nizamudeen A Date: Thu, 13 Jan 2022 18:28:56 +0530 Subject: [PATCH] mgr/dashboard: Refactoring dashboard cephadm checks I isolated all the tests suites into there respective files so that in future it is easier to add more tests to it. I also given priority to the host actions. Create OSD checks are now written in a way that OSDs are created only on the intended hosts. This will make the host draining process easier and less time consuming. Also tried to address the flaky force maintenance checks. Removed some duplicated codes Service creation part improved to reduce the time taken for its completion Fixes: https://tracker.ceph.com/issues/53905 Signed-off-by: Nizamudeen A --- .../mgr/dashboard/ci/cephadm/ceph_cluster.yml | 1 + .../integration/cluster/create-cluster.po.ts | 14 ------ .../cypress/integration/cluster/hosts.po.ts | 6 ++- .../cypress/integration/cluster/osds.po.ts | 22 ++++++--- .../integration/cluster/services.po.ts | 7 ++- .../02-create-cluster-add-host.e2e-spec.ts | 2 +- ...create-cluster-create-services.e2e-spec.ts | 17 +++---- .../04-create-cluster-create-osds.e2e-spec.ts | 33 +++++++------ .../workflow/06-cluster-check.e2e-spec.ts | 49 ------------------- .../orchestrator/workflow/07-osds.e2e-spec.ts | 22 +++++++++ .../workflow/08-hosts.e2e-spec.ts | 42 ++++++++++++++++ .../workflow/09-services.e2e-spec.ts | 27 ++++++++++ ...e2e-spec.ts => 10-nfs-exports.e2e-spec.ts} | 0 .../table-actions.component.html | 1 + 14 files changed, 143 insertions(+), 100 deletions(-) create mode 100644 src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/07-osds.e2e-spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/08-hosts.e2e-spec.ts create mode 100644 src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/09-services.e2e-spec.ts rename src/pybind/mgr/dashboard/frontend/cypress/integration/orchestrator/workflow/{07-nfs-exports.e2e-spec.ts => 10-nfs-exports.e2e-spec.ts} (100%) 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'); - - 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'); + 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); + + // 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 }} -- 2.47.3