<tabset *ngIf="selection.hasSingleSelection">
<tab i18n-heading
heading="Inventory"
- *ngIf="hostsPermission.read">
+ *ngIf="permissions.hosts.read">
<cd-inventory
- [hostname]="host['hostname']">
+ [hostname]="selection.first()['hostname']">
</cd-inventory>
</tab>
<tab i18n-heading
heading="Services"
- *ngIf="hostsPermission.read">
+ *ngIf="permissions.hosts.read">
<cd-services
- [hostname]="host['hostname']">
+ [hostname]="selection.first()['hostname']">
</cd-services>
</tab>
<tab i18n-heading
heading="Performance Details"
- *ngIf="grafanaPermission.read">
- <cd-grafana [grafanaPath]="'host-details?var-ceph_hosts=' + host['hostname']"
+ *ngIf="permissions.grafana.read">
+ <cd-grafana [grafanaPath]="'host-details?var-ceph_hosts=' + selection.first()['hostname']"
uid="rtOg0AiWz"
grafanaStyle="three">
</cd-grafana>
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { of } from 'rxjs';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
-import { TabsModule } from 'ngx-bootstrap/tabs';
+import { TabsetComponent, TabsModule } from 'ngx-bootstrap/tabs';
-import { configureTestBed } from '../../../../../testing/unit-test-helper';
+import { RouterTestingModule } from '@angular/router/testing';
+import { configureTestBed, i18nProviders } from '../../../../../testing/unit-test-helper';
+import { OrchestratorService } from '../../../../shared/api/orchestrator.service';
import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
+import { Permissions } from '../../../../shared/models/permissions';
import { SharedModule } from '../../../../shared/shared.module';
import { InventoryComponent } from '../../inventory/inventory.component';
import { ServicesComponent } from '../../services/services.component';
HttpClientTestingModule,
TabsModule.forRoot(),
BsDropdownModule.forRoot(),
+ RouterTestingModule,
SharedModule
],
- declarations: [HostDetailsComponent, InventoryComponent, ServicesComponent]
+ declarations: [HostDetailsComponent, InventoryComponent, ServicesComponent],
+ providers: [i18nProviders]
});
beforeEach(() => {
fixture = TestBed.createComponent(HostDetailsComponent);
component = fixture.componentInstance;
-
component.selection = new CdTableSelection();
-
+ component.permissions = new Permissions({
+ hosts: ['read'],
+ grafana: ['read']
+ });
+ const orchService = TestBed.get(OrchestratorService);
+ spyOn(orchService, 'status').and.returnValue(of({ available: true }));
+ spyOn(orchService, 'inventoryList').and.returnValue(of([]));
+ spyOn(orchService, 'serviceList').and.returnValue(of([]));
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ describe('Host details tabset', () => {
+ beforeEach(() => {
+ component.selection.selected = [
+ {
+ hostname: 'localhost'
+ }
+ ];
+ component.selection.update();
+ });
+
+ it('should recognize a tabset child', () => {
+ fixture.detectChanges();
+ const tabsetChild: TabsetComponent = component.tabsetChild;
+ expect(tabsetChild).toBeDefined();
+ });
+
+ it('should show tabs', () => {
+ fixture.detectChanges();
+ const tabs = component.tabsetChild.tabs;
+ expect(tabs.length).toBe(3);
+ expect(tabs[0].heading).toBe('Inventory');
+ expect(tabs[1].heading).toBe('Services');
+ expect(tabs[2].heading).toBe('Performance Details');
+ });
+ });
});
-import { Component, Input, OnChanges } from '@angular/core';
+import { Component, Input, ViewChild } from '@angular/core';
+
+import { TabsetComponent } from 'ngx-bootstrap/tabs';
import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
-import { Permission } from '../../../../shared/models/permissions';
-import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
+import { Permissions } from '../../../../shared/models/permissions';
@Component({
selector: 'cd-host-details',
templateUrl: './host-details.component.html',
styleUrls: ['./host-details.component.scss']
})
-export class HostDetailsComponent implements OnChanges {
- grafanaPermission: Permission;
- hostsPermission: Permission;
+export class HostDetailsComponent {
+ @Input()
+ permissions: Permissions;
@Input()
selection: CdTableSelection;
- host: any;
- constructor(private authStorageService: AuthStorageService) {
- this.grafanaPermission = this.authStorageService.getPermissions().grafana;
- this.hostsPermission = this.authStorageService.getPermissions().hosts;
- }
+ @ViewChild(TabsetComponent, { static: false })
+ tabsetChild: TabsetComponent;
- ngOnChanges() {
- if (this.selection.hasSelection) {
- this.host = this.selection.first();
- }
- }
+ constructor() {}
}
</span>
</ng-template>
<cd-host-details cdTableDetail
+ [permissions]="permissions"
[selection]="selection">
</cd-host-details>
</cd-table>
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
+import { of } from 'rxjs';
import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { OrchestratorService } from '../../../shared/api/orchestrator.service';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
import { SharedModule } from '../../../shared/shared.module';
import { InventoryComponent } from './inventory.component';
describe('InventoryComponent', () => {
let component: InventoryComponent;
let fixture: ComponentFixture<InventoryComponent>;
+ let reqHostname: string;
+
+ const inventoryNodes = [
+ {
+ name: 'host0',
+ devices: [
+ {
+ type: 'hdd',
+ id: '/dev/sda'
+ }
+ ]
+ },
+ {
+ name: 'host1',
+ devices: [
+ {
+ type: 'hdd',
+ id: '/dev/sda'
+ }
+ ]
+ }
+ ];
+
+ const getIventoryList = (hostname: String) => {
+ return hostname ? inventoryNodes.filter((node) => node.name === hostname) : inventoryNodes;
+ };
configureTestBed({
imports: [SharedModule, HttpClientTestingModule, RouterTestingModule],
beforeEach(() => {
fixture = TestBed.createComponent(InventoryComponent);
component = fixture.componentInstance;
+ const orchService = TestBed.get(OrchestratorService);
+ spyOn(orchService, 'status').and.returnValue(of({ available: true }));
+ reqHostname = '';
+ spyOn(orchService, 'inventoryList').and.callFake(() => of(getIventoryList(reqHostname)));
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should have columns that are sortable', () => {
+ expect(component.columns.every((column) => Boolean(column.prop))).toBeTruthy();
+ });
+
+ it('should return all devices', () => {
+ component.getInventory(new CdTableFetchDataContext(() => {}));
+ expect(component.devices.length).toBe(2);
+ });
+
+ it('should return devices on a host', () => {
+ reqHostname = 'host0';
+ component.getInventory(new CdTableFetchDataContext(() => {}));
+ expect(component.devices.length).toBe(1);
+ expect(component.devices[0].hostname).toBe(reqHostname);
+ });
});
styleUrls: ['./inventory.component.scss']
})
export class InventoryComponent implements OnChanges, OnInit {
- @ViewChild(TableComponent)
+ @ViewChild(TableComponent, { static: false })
table: TableComponent;
@Input() hostname = '';
-export interface Device {
- id: string;
+export class Device {
hostname: string;
uid: string;
+
+ blank: boolean;
+ type: string;
+ id: string;
+ size: number;
+ rotates: boolean;
+ available: boolean;
+ dev_id: string;
+ extended: any;
}
-export interface InventoryNode {
+export class InventoryNode {
name: string;
devices: Device[];
}
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
+import { of } from 'rxjs';
import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
+import { OrchestratorService } from '../../../shared/api/orchestrator.service';
+import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
import { SharedModule } from '../../../shared/shared.module';
import { ServicesComponent } from './services.component';
describe('ServicesComponent', () => {
let component: ServicesComponent;
let fixture: ComponentFixture<ServicesComponent>;
+ let reqHostname: string;
+
+ const services = [
+ {
+ nodename: 'host0',
+ service: '',
+ service_instance: 'x',
+ service_type: 'mon'
+ },
+ {
+ nodename: 'host0',
+ service: '',
+ service_instance: '0',
+ service_type: 'osd'
+ },
+ {
+ nodename: 'host1',
+ service: '',
+ service_instance: 'y',
+ service_type: 'mon'
+ },
+ {
+ nodename: 'host1',
+ service: '',
+ service_instance: '1',
+ service_type: 'osd'
+ }
+ ];
+
+ const getServiceList = (hostname: String) => {
+ return hostname ? services.filter((service) => service.nodename === hostname) : services;
+ };
configureTestBed({
imports: [SharedModule, HttpClientTestingModule, RouterTestingModule],
beforeEach(() => {
fixture = TestBed.createComponent(ServicesComponent);
component = fixture.componentInstance;
+ const orchService = TestBed.get(OrchestratorService);
+ spyOn(orchService, 'status').and.returnValue(of({ available: true }));
+ reqHostname = '';
+ spyOn(orchService, 'serviceList').and.callFake(() => of(getServiceList(reqHostname)));
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should have columns that are sortable', () => {
+ expect(component.columns.every((column) => Boolean(column.prop))).toBeTruthy();
+ });
+
+ it('should return all services', () => {
+ component.getServices(new CdTableFetchDataContext(() => {}));
+ expect(component.services.length).toBe(4);
+ });
+
+ it('should return services on a host', () => {
+ reqHostname = 'host0';
+ component.getServices(new CdTableFetchDataContext(() => {}));
+ expect(component.services.length).toBe(2);
+ expect(component.services[0].nodename).toBe(reqHostname);
+ expect(component.services[1].nodename).toBe(reqHostname);
+ });
});
styleUrls: ['./services.component.scss']
})
export class ServicesComponent implements OnChanges, OnInit {
- @ViewChild(TableComponent)
+ @ViewChild(TableComponent, { static: false })
table: TableComponent;
@Input() hostname = '';
docsUrl: string;
columns: Array<CdTableColumn> = [];
- services: Array<object> = [];
+ services: Array<Service> = [];
isLoadingServices = false;
constructor(
(data: Service[]) => {
const services: Service[] = [];
data.forEach((service: Service) => {
- service.uid = `${service.nodename}-${service.service_type}-${service.service}-${
- service.service_instance
- }`;
+ service.uid = `${service.nodename}-${service.service_type}-${service.service}-${service.service_instance}`;
services.push(service);
});
this.services = services;
-export interface Service {
+export class Service {
uid: string;
+
nodename: string;
- service_type: string;
+ container_id: string;
service: string;
service_instance: string;
+ service_type: string;
+ version: string;
+ rados_config_location: string;
+ service_url: string;
+ status: string;
+ status_desc: string;
}