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 894d5d086eae..bdd84b7f1cdb 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 52be703af28e..819afd559b12 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 f2be649ae5fe..ffac83ba67bf 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 862c7c6011d4..d388a3c5ba6e 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 2d1969b75bd0..07bd3b58b8b7 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 0310e473ec23..02b61167de3b 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 e1b33fea34f7..d52c7d53864c 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 c8d93b479623..268cf0ad7862 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 ff6017559f2e..531a31b339d3 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 000000000000..90db14668f71 --- /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 000000000000..942321542b89 --- /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 000000000000..9b49c75aca6a --- /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 b60c9b1ddb42..9896d56206d2 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