]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: rbd-mirroring e2e tests
authorNizamudeen A <nia@redhat.com>
Mon, 4 Jul 2022 07:39:43 +0000 (13:09 +0530)
committerNizamudeen A <nia@redhat.com>
Tue, 26 Jul 2022 08:20:23 +0000 (13:50 +0530)
Signed-off-by: Nizamudeen A <nia@redhat.com>
src/pybind/mgr/dashboard/frontend/cypress.json
src/pybind/mgr/dashboard/frontend/cypress/integration/block/mirroring.e2e-spec.ts
src/pybind/mgr/dashboard/frontend/cypress/integration/block/mirroring.po.ts
src/pybind/mgr/dashboard/frontend/cypress/support/commands.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/components/back-button/back-button.component.html
src/pybind/mgr/dashboard/run-frontend-e2e-tests.sh

index 0de1008cb54023183884024bbfa583f78cf958c1..996b285301fe99ed374437d9b0fabeec07728506 100644 (file)
@@ -21,6 +21,9 @@
   "retries": 1,
   "env": {
     "LOGIN_USER": "admin",
-    "LOGIN_PWD": "admin"
-  }
+    "LOGIN_PWD": "admin",
+    "CEPH2_URL": "http://localhost:4202/"
+  },
+  "experimentalSessionAndOrigin": true,
+  "chromeWebSecurity": false
 }
index dfba73b27409d98f34065c1c1212eb0621a6c894..77deca7012e2645c80332340561eae4d6ed77be2 100644 (file)
@@ -25,6 +25,67 @@ describe('Mirroring page', () => {
     mirroring.getTabText(2).should('eq', 'Ready (0)');
   });
 
+  describe('rbd mirroring bootstrap', () => {
+    const poolName = 'rbd-mirror';
+
+    beforeEach(() => {
+      cy.login();
+      Cypress.Cookies.preserveOnce('token');
+      pools.navigateTo('create');
+      pools.create(poolName, 8, 'rbd');
+      pools.navigateTo();
+      pools.existTableCell(poolName, true);
+      mirroring.navigateTo();
+    });
+
+    it('should generate and import the bootstrap token between clusters', () => {
+      const url: string = Cypress.env('CEPH2_URL');
+      mirroring.navigateTo();
+      mirroring.generateToken(poolName);
+      cy.get('@token').then((bootstrapToken) => {
+        // pass the token to the origin as an arg
+        const args = { name: poolName, token: String(bootstrapToken) };
+
+        // login to the second ceph cluster
+        cy.ceph2Login();
+
+        // can't use any imports or functions inside the origin
+        // so writing the code to copy the token inside the origin manually
+        // rather than using a function call
+        // @ts-ignore
+        cy.origin(url, { args }, ({ name, token }: any) => {
+          // Create an rbd pool in the second cluster
+          cy.visit('#/pool/create').wait(100);
+          cy.get('input[name=name]').clear().type(name);
+          cy.get(`select[name=poolType]`).select('replicated');
+          cy.get(`select[name=poolType] option:checked`).contains('replicated');
+          cy.get('.float-left.mr-2.select-menu-edit').click();
+          cy.get('.popover-body').should('be.visible');
+          // Choose rbd as the application label
+          cy.get('.select-menu-item-content').contains('rbd').click();
+          cy.get('cd-submit-button').click();
+          cy.get('cd-pool-list').should('exist');
+
+          cy.visit('#/block/mirroring').wait(1000);
+          cy.get('.table-actions button.dropdown-toggle').first().click();
+          cy.get('[aria-label="Import Bootstrap Token"]').click();
+          cy.get('cd-bootstrap-import-modal').within(() => {
+            cy.get(`label[for=${name}]`).click();
+            cy.get('textarea[id=token]').wait(100).type(token);
+            cy.get('button[type=submit]').click();
+          });
+        });
+      });
+
+      // login again since origin removes all the cookies
+      // sessions, localStorage items etc..
+      cy.login();
+      Cypress.Cookies.preserveOnce('token');
+      mirroring.navigateTo();
+      mirroring.checkPoolHealthStatus(poolName, 'OK');
+    });
+  });
+
   describe('checks that edit mode functionality shows in the pools table', () => {
     const poolName = 'mirroring_test';
 
index e24a3ebc037abbc8b1b2fd619fe89e57e86d3f54..456223a873ec138243a38fd6dc8e7d4f81872aaf 100644 (file)
@@ -7,6 +7,11 @@ const pages = {
 export class MirroringPageHelper extends PageHelper {
   pages = pages;
 
+  poolsColumnIndex = {
+    name: 1,
+    health: 6
+  };
+
   /**
    * Goes to the mirroring page and edits a pool in the Pool table. Clicks on the
    * pool and chooses an option (either pool, image, or disabled)
@@ -32,4 +37,28 @@ export class MirroringPageHelper extends PageHelper {
     // unselect the pool in the table
     this.getFirstTableCell(name).click();
   }
+
+  @PageHelper.restrictTo(pages.index.url)
+  generateToken(poolName: string) {
+    cy.get('[aria-label="Create Bootstrap Token"]').first().click();
+    cy.get('cd-bootstrap-create-modal').within(() => {
+      cy.get(`label[for=${poolName}]`).click();
+      cy.get('button[type=submit]').click();
+      cy.get('textarea[id=token]').wait(200).invoke('val').as('token');
+      cy.get('[aria-label="Back"]').click();
+    });
+  }
+
+  @PageHelper.restrictTo(pages.index.url)
+  checkPoolHealthStatus(poolName: string, status: string) {
+    cy.get('cd-mirroring-pools').within(() => {
+      this.getTableCell(this.poolsColumnIndex.name, poolName)
+        .parent()
+        .find(`datatable-body-cell:nth-child(${this.poolsColumnIndex.health}) .badge`)
+        .should(($ele) => {
+          const newLabels = $ele.toArray().map((v) => v.innerText);
+          expect(newLabels).to.include(status);
+        });
+    });
+  }
 }
index 768d852768666d793f71e66487352955633a959f..cdd39c680b7ad6f2d56510f13e504bd008ff28fc 100644 (file)
@@ -1,9 +1,10 @@
 declare global {
   namespace Cypress {
     interface Chainable<Subject> {
-      login(): void;
+      login(username?: string, password?: string): void;
       logToConsole(message: string, optional?: any): void;
       text(): Chainable<string>;
+      ceph2Login(username?: string, password?: string): Chainable<any>;
     }
   }
 }
@@ -26,29 +27,58 @@ const fillAuth = () => {
   window.localStorage.setItem('sso', auth.sso);
 };
 
-Cypress.Commands.add('login', () => {
-  const username = Cypress.env('LOGIN_USER');
-  const password = Cypress.env('LOGIN_PWD');
-
-  if (auth === undefined) {
-    cy.request({
-      method: 'POST',
-      url: 'api/auth',
-      headers: { Accept: CdHelperClass.cdVersionHeader('1', '0') },
-      body: { username: username, password: password }
-    }).then((resp) => {
-      auth = resp.body;
-      auth.permissions = JSON.stringify(new Permissions(auth.permissions));
-      auth.pwdExpirationDate = String(auth.pwdExpirationDate);
-      auth.pwdUpdateRequired = String(auth.pwdUpdateRequired);
-      auth.sso = String(auth.sso);
-      fillAuth();
-    });
-  } else {
+Cypress.Commands.add('login', (username, password) => {
+  requestAuth(username, password).then((resp) => {
+    auth = resp.body;
+    auth.permissions = JSON.stringify(new Permissions(auth.permissions));
+    auth.pwdExpirationDate = String(auth.pwdExpirationDate);
+    auth.pwdUpdateRequired = String(auth.pwdUpdateRequired);
+    auth.sso = String(auth.sso);
     fillAuth();
-  }
+  });
+});
+
+Cypress.Commands.add('ceph2Login', (username, password) => {
+  const url: string = Cypress.env('CEPH2_URL');
+  requestAuth(username, password, url).then((resp) => {
+    auth = resp.body;
+    auth.permissions = JSON.stringify(new Permissions(auth.permissions));
+    auth.pwdExpirationDate = String(auth.pwdExpirationDate);
+    auth.pwdUpdateRequired = String(auth.pwdUpdateRequired);
+    auth.sso = String(auth.sso);
+    const args = {
+      username: auth.username,
+      permissions: auth.permissions,
+      pwdExpirationDate: auth.pwdExpirationDate,
+      pwdUpdateRequired: auth.pwdUpdateRequired,
+      sso: auth.sso
+    };
+    // @ts-ignore
+    cy.origin(
+      url,
+      { args },
+      ({ uname, permissions, pwdExpirationDate, pwdUpdateRequired, sso }: any) => {
+        window.localStorage.setItem('dashboard_username', uname);
+        window.localStorage.setItem('dashboard_permissions', permissions);
+        window.localStorage.setItem('user_pwd_expiration_date', pwdExpirationDate);
+        window.localStorage.setItem('user_pwd_update_required', pwdUpdateRequired);
+        window.localStorage.setItem('sso', sso);
+      }
+    );
+  });
 });
 
+function requestAuth(username: string, password: string, url = '') {
+  username = username ? username : Cypress.env('LOGIN_USER');
+  password = password ? password : Cypress.env('LOGIN_PWD');
+  return cy.request({
+    method: 'POST',
+    url: !url ? 'api/auth' : `${url}api/auth`,
+    headers: { Accept: CdHelperClass.cdVersionHeader('1', '0') },
+    body: { username: username, password: password }
+  });
+}
+
 // @ts-ignore
 Cypress.Commands.add('text', { prevSubject: true }, (subject: any) => {
   return subject.text();
index a9090aaf2022d9e441f7d3e61d85ed944d9b9800..2d8a787c0d1467dda572d6c1357d6ecccd3f8c1e 100644 (file)
@@ -1,4 +1,5 @@
 <button class="btn btn-light tc_backButton"
+        aria-label="Back"
         (click)="back()"
         type="button">
   {{ name }}
index 9cdbc6ac1b68cd32a6354057c2c93fac7141c155..9cb4ae7ec7b7ec46da16c939b84f6103c8408d6e 100755 (executable)
@@ -33,7 +33,12 @@ start_ceph() {
     ceph_all dashboard set-rgw-api-ssl-verify False
 
     CYPRESS_BASE_URL=$(ceph mgr services | jq -r .dashboard)
-    CEPH2_DASHBOARD_URL=$(ceph2 mgr services | jq -r .dashboard)
+    CYPRESS_CEPH2_URL=$(ceph2 mgr services | jq -r .dashboard)
+
+    # start rbd-mirror daemon in the cluster
+    KEY=$(ceph auth get client.admin --format=json | jq -r .[0].key)
+    MON_CLUSTER_1=$(grep "mon host" ${FULL_PATH_BUILD_DIR}/run/1/ceph.conf | awk '{print $4}')
+    ${FULL_PATH_BUILD_DIR}/bin/rbd-mirror --mon_host $MON_CLUSTER_1 --key $KEY -c ${FULL_PATH_BUILD_DIR}/run/1/ceph.conf &
 
     set +x
 }
@@ -76,7 +81,7 @@ check_device_available() {
 }
 
 : ${CYPRESS_BASE_URL:=''}
-: ${CEPH2_DASHBOARD_URL:=''}
+: ${CYPRESS_CEPH2_URL:=''}
 : ${CYPRESS_LOGIN_PWD:=''}
 : ${CYPRESS_LOGIN_USER:=''}
 : ${DEVICE:="chrome"}
@@ -103,7 +108,7 @@ FULL_PATH_BUILD_DIR=`pwd`
 
 : ${CYPRESS_CACHE_FOLDER:="${FULL_PATH_BUILD_DIR}/src/pybind/mgr/dashboard/cypress"}
 
-export CYPRESS_BASE_URL CYPRESS_CACHE_FOLDER CYPRESS_LOGIN_USER CYPRESS_LOGIN_PWD NO_COLOR CEPH2_DASHBOARD_URL
+export CYPRESS_BASE_URL CYPRESS_CACHE_FOLDER CYPRESS_LOGIN_USER CYPRESS_LOGIN_PWD NO_COLOR CYPRESS_CEPH2_URL
 
 check_device_available
 
@@ -126,7 +131,7 @@ case "$DEVICE" in
             --env CYPRESS_BASE_URL \
             --env CYPRESS_LOGIN_USER \
             --env CYPRESS_LOGIN_PWD \
-            --env CEPH2_DASHBOARD_URL \
+            --env CYPRESS_CEPH2_URL \
             --name=e2e \
             --network=host \
             cypress/included:${CYPRESS_VERSION} || failed=1