Merge pull request #38209 from votdev/issue_44404_placement_column

mgr/dashboard: display placement column in service table

Reviewed-by: Avan Thakkar <athakkar@redhat.com>
Reviewed-by: Kiefer Chang <kiefer.chang@suse.com>
Reviewed-by: Ernesto Puerta <epuertat@redhat.com>
Reviewed-by: Nizamudeen A <nia@redhat.com>
Reviewed-by: Tatjana Dehler <tdehler@suse.com>
This commit is contained in:
Ernesto Puerta 2020-11-30 11:33:07 +01:00 committed by GitHub
commit 6911e753b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 1 deletions

View File

@ -47,6 +47,7 @@ import { RulesListComponent } from './prometheus/rules-list/rules-list.component
import { SilenceFormComponent } from './prometheus/silence-form/silence-form.component';
import { SilenceListComponent } from './prometheus/silence-list/silence-list.component';
import { SilenceMatcherModalComponent } from './prometheus/silence-matcher-modal/silence-matcher-modal.component';
import { PlacementPipe } from './services/placement.pipe';
import { ServiceDaemonListComponent } from './services/service-daemon-list/service-daemon-list.component';
import { ServiceDetailsComponent } from './services/service-details/service-details.component';
import { ServiceFormComponent } from './services/service-form/service-form.component';
@ -108,7 +109,8 @@ import { TelemetryComponent } from './telemetry/telemetry.component';
TelemetryComponent,
PrometheusTabsComponent,
ServiceFormComponent,
OsdFlagsIndivModalComponent
OsdFlagsIndivModalComponent,
PlacementPipe
]
})
export class ClusterModule {}

View File

@ -0,0 +1,78 @@
import { PlacementPipe } from './placement.pipe';
describe('PlacementPipe', () => {
const pipe = new PlacementPipe();
it('create an instance', () => {
expect(pipe).toBeTruthy();
});
it('transforms to no spec', () => {
expect(pipe.transform(undefined)).toBe('no spec');
});
it('transforms to unmanaged', () => {
expect(pipe.transform({ unmanaged: true })).toBe('unmanaged');
});
it('transforms placement (1)', () => {
expect(
pipe.transform({
placement: {
hosts: ['mon0']
}
})
).toBe('mon0');
});
it('transforms placement (2)', () => {
expect(
pipe.transform({
placement: {
hosts: ['mon0', 'mgr0']
}
})
).toBe('mon0;mgr0');
});
it('transforms placement (3)', () => {
expect(
pipe.transform({
placement: {
count: 1
}
})
).toBe('count:1');
});
it('transforms placement (4)', () => {
expect(
pipe.transform({
placement: {
label: 'foo'
}
})
).toBe('label:foo');
});
it('transforms placement (5)', () => {
expect(
pipe.transform({
placement: {
host_pattern: '*'
}
})
).toBe('*');
});
it('transforms placement (6)', () => {
expect(
pipe.transform({
placement: {
count: 2,
hosts: ['mon0', 'mgr0']
}
})
).toBe('mon0;mgr0;count:2');
});
});

View File

@ -0,0 +1,41 @@
import { Pipe, PipeTransform } from '@angular/core';
import _ from 'lodash';
@Pipe({
name: 'placement'
})
export class PlacementPipe implements PipeTransform {
/**
* Convert the placement configuration into human readable form.
* The output is equal to the column 'PLACEMENT' in 'ceph orch ls'.
* @param serviceSpec The service specification to process.
* @return The placement configuration as human readable string.
*/
transform(serviceSpec: object | undefined): string {
if (_.isUndefined(serviceSpec)) {
return $localize`no spec`;
}
if (_.get(serviceSpec, 'unmanaged', false)) {
return $localize`unmanaged`;
}
const kv: Array<any> = [];
const hosts: Array<string> = _.get(serviceSpec, 'placement.hosts');
const count: number = _.get(serviceSpec, 'placement.count');
const label: string = _.get(serviceSpec, 'placement.label');
const hostPattern: string = _.get(serviceSpec, 'placement.host_pattern');
if (_.isArray(hosts)) {
kv.push(...hosts);
}
if (_.isNumber(count)) {
kv.push($localize`count:${count}`);
}
if (_.isString(label)) {
kv.push($localize`label:${label}`);
}
if (_.isString(hostPattern)) {
kv.push(...hostPattern);
}
return kv.join(';');
}
}

View File

@ -82,7 +82,10 @@ describe('ServicesComponent', () => {
it('should have columns that are sortable', () => {
expect(
component.columns
// Filter the 'Expand/Collapse Row' column.
.filter((column) => !(column.cellClass === 'cd-datatable-expand-collapse'))
// Filter the 'Placement' column.
.filter((column) => !(column.prop === ''))
.every((column) => Boolean(column.prop))
).toBeTruthy();
});

View File

@ -24,6 +24,7 @@ import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
import { ModalService } from '~/app/shared/services/modal.service';
import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
import { URLBuilderService } from '~/app/shared/services/url-builder.service';
import { PlacementPipe } from './placement.pipe';
const BASE_URL = 'services';
@ -108,6 +109,12 @@ export class ServicesComponent extends ListWithDetails implements OnChanges, OnI
length: 12
}
},
{
name: $localize`Placement`,
prop: '',
pipe: new PlacementPipe(),
flexGrow: 1
},
{
name: $localize`Running`,
prop: 'status.running',