Skip to content

Commit

Permalink
mgr/dashboard: display placement column in service table
Browse files Browse the repository at this point in the history
Fixes: https://tracker.ceph.com/issues/44404

Signed-off-by: Volker Theile <[email protected]>
  • Loading branch information
votdev committed Nov 23, 2020
1 parent 2f0fe91 commit 1c722aa
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -108,7 +109,8 @@ import { TelemetryComponent } from './telemetry/telemetry.component';
TelemetryComponent,
PrometheusTabsComponent,
ServiceFormComponent,
OsdFlagsIndivModalComponent
OsdFlagsIndivModalComponent,
PlacementPipe
]
})
export class ClusterModule {}
Original file line number Diff line number Diff line change
@@ -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');
});
});
Original file line number Diff line number Diff line change
@@ -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(';');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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',
Expand Down

0 comments on commit 1c722aa

Please sign in to comment.