]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Review Section for the Create Cluster Workflow
authorAvan Thakkar <athakkar@localhost.localdomain>
Fri, 9 Jul 2021 13:27:35 +0000 (18:57 +0530)
committerNizamudeen A <nia@redhat.com>
Wed, 13 Oct 2021 10:26:09 +0000 (15:56 +0530)
Fixes: https://tracker.ceph.com/issues/50566
Signed-off-by: Avan Thakkar <athakkar@redhat.com>
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.html [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.scss [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.spec.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.ts [new file with mode: 0644]
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.spec.ts

index 185c34b27504dd640f785a47141cefc285b33c2e..610bb79baebc781eea8a1f2e4f78a40b04ea007d 100644 (file)
@@ -22,6 +22,7 @@ import { CephSharedModule } from '../shared/ceph-shared.module';
 import { ConfigurationDetailsComponent } from './configuration/configuration-details/configuration-details.component';
 import { ConfigurationFormComponent } from './configuration/configuration-form/configuration-form.component';
 import { ConfigurationComponent } from './configuration/configuration.component';
+import { CreateClusterReviewComponent } from './create-cluster/create-cluster-review.component';
 import { CreateClusterComponent } from './create-cluster/create-cluster.component';
 import { CrushmapComponent } from './crushmap/crushmap.component';
 import { HostDetailsComponent } from './hosts/host-details/host-details.component';
@@ -114,7 +115,8 @@ import { TelemetryComponent } from './telemetry/telemetry.component';
     ServiceFormComponent,
     OsdFlagsIndivModalComponent,
     PlacementPipe,
-    CreateClusterComponent
+    CreateClusterComponent,
+    CreateClusterReviewComponent
   ],
   providers: [NgbActiveModal]
 })
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.html
new file mode 100644 (file)
index 0000000..fa010fd
--- /dev/null
@@ -0,0 +1,31 @@
+<div class="row">
+  <div class="col-lg-4">
+    <fieldset>
+      <legend class="cd-header"
+              i18n>Cluster Resources</legend>
+      <table class="table table-striped">
+        <tr>
+          <td i18n
+              class="bold">Hosts</td>
+          <td>{{ hostsCount }}</td>
+        </tr>
+      </table>
+    </fieldset>
+  </div>
+
+  <div class="col-lg-8">
+    <legend i18n
+            class="cd-header">Hosts by Label</legend>
+    <cd-table [data]="hostsByLabel['data']"
+              [columns]="hostsByLabel['columns']"
+              [toolHeader]="false">
+    </cd-table>
+
+    <legend i18n
+            class="cd-header">Host Details</legend>
+    <cd-table [data]="hostsDetails['data']"
+              [columns]="hostsDetails['columns']"
+              [toolHeader]="false">
+    </cd-table>
+  </div>
+</div>
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.scss
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.spec.ts
new file mode 100644 (file)
index 0000000..e823932
--- /dev/null
@@ -0,0 +1,61 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import _ from 'lodash';
+import { of } from 'rxjs';
+
+import { CephModule } from '~/app/ceph/ceph.module';
+import { CoreModule } from '~/app/core/core.module';
+import { HostService } from '~/app/shared/api/host.service';
+import { SharedModule } from '~/app/shared/shared.module';
+import { configureTestBed } from '~/testing/unit-test-helper';
+import { CreateClusterReviewComponent } from './create-cluster-review.component';
+
+describe('CreateClusterReviewComponent', () => {
+  let component: CreateClusterReviewComponent;
+  let fixture: ComponentFixture<CreateClusterReviewComponent>;
+  let hostService: HostService;
+  let hostListSpy: jasmine.Spy;
+
+  configureTestBed({
+    imports: [HttpClientTestingModule, SharedModule, CoreModule, CephModule]
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(CreateClusterReviewComponent);
+    component = fixture.componentInstance;
+    hostService = TestBed.inject(HostService);
+    hostListSpy = spyOn(hostService, 'list');
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should verify host metadata calculations', () => {
+    const hostnames = ['ceph.test1', 'ceph.test2'];
+    const payload = [
+      {
+        hostname: hostnames[0],
+        ceph_version: 'ceph version Development',
+        labels: ['foo', 'bar']
+      },
+      {
+        hostname: hostnames[1],
+        ceph_version: 'ceph version Development',
+        labels: ['foo1', 'bar1']
+      }
+    ];
+    hostListSpy.and.callFake(() => of(payload));
+    fixture.detectChanges();
+    expect(hostListSpy).toHaveBeenCalled();
+
+    expect(component.hostsCount).toBe(2);
+    expect(component.uniqueLabels.size).toBe(4);
+    const labels = ['foo', 'bar', 'foo1', 'bar1'];
+
+    labels.forEach((label) => {
+      expect(component.labelOccurrences[label]).toBe(1);
+    });
+  });
+});
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster-review.component.ts
new file mode 100644 (file)
index 0000000..c78e8f9
--- /dev/null
@@ -0,0 +1,86 @@
+import { Component, OnInit } from '@angular/core';
+
+import _ from 'lodash';
+
+import { HostService } from '~/app/shared/api/host.service';
+import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
+
+@Component({
+  selector: 'cd-create-cluster-review',
+  templateUrl: './create-cluster-review.component.html',
+  styleUrls: ['./create-cluster-review.component.scss']
+})
+export class CreateClusterReviewComponent implements OnInit {
+  hosts: object[] = [];
+  hostsDetails: object;
+  hostsByLabel: object;
+  hostsCount: number;
+  labelOccurrences = {};
+  hostsCountPerLabel: object[] = [];
+  uniqueLabels: Set<string> = new Set();
+
+  constructor(private hostService: HostService) {}
+
+  ngOnInit() {
+    this.hostsDetails = {
+      columns: [
+        {
+          prop: 'hostname',
+          name: $localize`Host Name`,
+          flexGrow: 2
+        },
+        {
+          name: $localize`Labels`,
+          prop: 'labels',
+          flexGrow: 1,
+          cellTransformation: CellTemplate.badge,
+          customTemplateConfig: {
+            class: 'badge-dark'
+          }
+        }
+      ]
+    };
+
+    this.hostsByLabel = {
+      columns: [
+        {
+          prop: 'label',
+          name: $localize`Labels`,
+          flexGrow: 1,
+          cellTransformation: CellTemplate.badge,
+          customTemplateConfig: {
+            class: 'badge-dark'
+          }
+        },
+        {
+          name: $localize`Number of Hosts`,
+          prop: 'hosts_per_label',
+          flexGrow: 1
+        }
+      ]
+    };
+
+    this.hostService.list().subscribe((resp: object[]) => {
+      this.hosts = resp;
+      this.hostsCount = this.hosts.length;
+
+      _.forEach(this.hosts, (hostKey) => {
+        const labels = hostKey['labels'];
+        _.forEach(labels, (label) => {
+          this.labelOccurrences[label] = (this.labelOccurrences[label] || 0) + 1;
+          this.uniqueLabels.add(label);
+        });
+      });
+
+      this.uniqueLabels.forEach((label) => {
+        this.hostsCountPerLabel.push({
+          label: label,
+          hosts_per_label: this.labelOccurrences[label]
+        });
+      });
+
+      this.hostsByLabel['data'] = [...this.hostsCountPerLabel];
+      this.hostsDetails['data'] = [...this.hosts];
+    });
+  }
+}
index fb006ec1beb104d31253ee4fe0cb8ca382c8c595..38887328ec3ab75c804aa88aaeeac690b5941d79 100644 (file)
         </div>
         <div *ngSwitchCase="'2'"
              class="ml-5">
-          <h4 class="title"
-              i18n>Review</h4>
-          <br>
-          <p>To be implemented</p>
+          <cd-create-cluster-review></cd-create-cluster-review>
         </div>
       </ng-container>
     </div>
index 1ebdfb3a59d2f93ea46012b5929ece2723804e02..b0564703840d47043226df2abe85b6d2d67f04d5 100644 (file)
@@ -90,10 +90,8 @@ describe('CreateClusterComponent', () => {
     fixture.detectChanges();
     component.onNextStep();
     fixture.detectChanges();
-    const heading = fixture.debugElement.query(By.css('.title')).nativeElement;
     expect(wizardStepServiceSpy).toHaveBeenCalledTimes(1);
-    expect(hostServiceSpy).toBeCalledTimes(1);
-    expect(heading.innerHTML).toBe('Review');
+    expect(hostServiceSpy).toBeCalledTimes(2);
   });
 
   it('should show the button labels correctly', () => {