]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-daemon-list/service-daemon-list.component.spec.ts
31739a7c2988f26875bfd381d3ed99b787dfc730
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / services / service-daemon-list / service-daemon-list.component.spec.ts
1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3
4 import _ from 'lodash';
5 import { NgxPipeFunctionModule } from 'ngx-pipe-function';
6 import { ToastrModule } from 'ngx-toastr';
7 import { of } from 'rxjs';
8
9 import { CephModule } from '~/app/ceph/ceph.module';
10 import { CoreModule } from '~/app/core/core.module';
11 import { CephServiceService } from '~/app/shared/api/ceph-service.service';
12 import { HostService } from '~/app/shared/api/host.service';
13 import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context';
14 import { SharedModule } from '~/app/shared/shared.module';
15 import { configureTestBed } from '~/testing/unit-test-helper';
16 import { ServiceDaemonListComponent } from './service-daemon-list.component';
17
18 describe('ServiceDaemonListComponent', () => {
19 let component: ServiceDaemonListComponent;
20 let fixture: ComponentFixture<ServiceDaemonListComponent>;
21
22 const daemons = [
23 {
24 hostname: 'osd0',
25 container_id: '003c10beafc8c27b635bcdfed1ed832e4c1005be89bb1bb05ad4cc6c2b98e41b',
26 container_image_id: 'e70344c77bcbf3ee389b9bf5128f635cf95f3d59e005c5d8e67fc19bcc74ed23',
27 container_image_name: 'docker.io/ceph/daemon-base:latest-master-devel',
28 daemon_id: '3',
29 daemon_type: 'osd',
30 daemon_name: 'osd.3',
31 version: '15.1.0-1174-g16a11f7',
32 memory_usage: '17.7',
33 cpu_percentage: '3.54%',
34 status: 1,
35 status_desc: 'running',
36 last_refresh: '2020-02-25T04:33:26.465699',
37 events: [
38 { created: '2020-02-24T04:33:26.465699' },
39 { created: '2020-02-25T04:33:26.465699' },
40 { created: '2020-02-26T04:33:26.465699' }
41 ]
42 },
43 {
44 hostname: 'osd0',
45 container_id: 'baeec41a01374b3ed41016d542d19aef4a70d69c27274f271e26381a0cc58e7a',
46 container_image_id: 'e70344c77bcbf3ee389b9bf5128f635cf95f3d59e005c5d8e67fc19bcc74ed23',
47 container_image_name: 'docker.io/ceph/daemon-base:latest-master-devel',
48 daemon_id: '4',
49 daemon_type: 'osd',
50 daemon_name: 'osd.4',
51 version: '15.1.0-1174-g16a11f7',
52 memory_usage: '17.7',
53 cpu_percentage: '3.54%',
54 status: 1,
55 status_desc: 'running',
56 last_refresh: '2020-02-25T04:33:26.465822',
57 events: []
58 },
59 {
60 hostname: 'osd0',
61 container_id: '8483de277e365bea4365cee9e1f26606be85c471e4da5d51f57e4b85a42c616e',
62 container_image_id: 'e70344c77bcbf3ee389b9bf5128f635cf95f3d59e005c5d8e67fc19bcc74ed23',
63 container_image_name: 'docker.io/ceph/daemon-base:latest-master-devel',
64 daemon_id: '5',
65 daemon_type: 'osd',
66 daemon_name: 'osd.5',
67 version: '15.1.0-1174-g16a11f7',
68 memory_usage: '17.7',
69 cpu_percentage: '3.54%',
70 status: 1,
71 status_desc: 'running',
72 last_refresh: '2020-02-25T04:33:26.465886',
73 events: []
74 },
75 {
76 hostname: 'mon0',
77 container_id: '6ca0574f47e300a6979eaf4e7c283a8c4325c2235ae60358482fc4cd58844a21',
78 container_image_id: 'e70344c77bcbf3ee389b9bf5128f635cf95f3d59e005c5d8e67fc19bcc74ed23',
79 container_image_name: 'docker.io/ceph/daemon-base:latest-master-devel',
80 daemon_id: 'a',
81 daemon_name: 'mon.a',
82 daemon_type: 'mon',
83 version: '15.1.0-1174-g16a11f7',
84 memory_usage: '17.7',
85 cpu_percentage: '3.54%',
86 status: 1,
87 status_desc: 'running',
88 last_refresh: '2020-02-25T04:33:26.465886',
89 events: []
90 }
91 ];
92
93 const services = [
94 {
95 service_type: 'osd',
96 service_name: 'osd',
97 status: {
98 container_image_id: 'e70344c77bcbf3ee389b9bf5128f635cf95f3d59e005c5d8e67fc19bcc74ed23',
99 container_image_name: 'docker.io/ceph/daemon-base:latest-master-devel',
100 size: 3,
101 running: 3,
102 last_refresh: '2020-02-25T04:33:26.465699'
103 },
104 events: '2021-03-22T07:34:48.582163Z service:osd [INFO] "service was created"'
105 },
106 {
107 service_type: 'crash',
108 service_name: 'crash',
109 status: {
110 container_image_id: 'e70344c77bcbf3ee389b9bf5128f635cf95f3d59e005c5d8e67fc19bcc74ed23',
111 container_image_name: 'docker.io/ceph/daemon-base:latest-master-devel',
112 size: 1,
113 running: 1,
114 last_refresh: '2020-02-25T04:33:26.465766'
115 },
116 events: '2021-03-22T07:34:48.582163Z service:osd [INFO] "service was created"'
117 }
118 ];
119
120 const getDaemonsByHostname = (hostname?: string) => {
121 return hostname ? _.filter(daemons, { hostname: hostname }) : daemons;
122 };
123
124 const getDaemonsByServiceName = (serviceName?: string) => {
125 return serviceName ? _.filter(daemons, { daemon_type: serviceName }) : daemons;
126 };
127
128 configureTestBed({
129 imports: [
130 HttpClientTestingModule,
131 CephModule,
132 CoreModule,
133 NgxPipeFunctionModule,
134 SharedModule,
135 ToastrModule.forRoot()
136 ]
137 });
138
139 beforeEach(() => {
140 fixture = TestBed.createComponent(ServiceDaemonListComponent);
141 component = fixture.componentInstance;
142 const hostService = TestBed.inject(HostService);
143 const cephServiceService = TestBed.inject(CephServiceService);
144 spyOn(hostService, 'getDaemons').and.callFake(() =>
145 of(getDaemonsByHostname(component.hostname))
146 );
147 spyOn(cephServiceService, 'getDaemons').and.callFake(() =>
148 of(getDaemonsByServiceName(component.serviceName))
149 );
150 spyOn(cephServiceService, 'list').and.returnValue(of(services));
151 fixture.detectChanges();
152 });
153
154 it('should create', () => {
155 expect(component).toBeTruthy();
156 });
157
158 it('should list daemons by host', () => {
159 component.hostname = 'mon0';
160 component.getDaemons(new CdTableFetchDataContext(() => undefined));
161 expect(component.daemons.length).toBe(1);
162 });
163
164 it('should list daemons by service', () => {
165 component.serviceName = 'osd';
166 component.getDaemons(new CdTableFetchDataContext(() => undefined));
167 expect(component.daemons.length).toBe(3);
168 });
169
170 it('should list services', () => {
171 component.getServices(new CdTableFetchDataContext(() => undefined));
172 expect(component.services.length).toBe(2);
173 });
174
175 it('should not display doc panel if orchestrator is available', () => {
176 expect(component.showDocPanel).toBeFalsy();
177 });
178
179 it('should call daemon action', () => {
180 const daemon = daemons[0];
181 component.selection.selected = [daemon];
182 component['daemonService'].action = jest.fn(() => of());
183 for (const action of ['start', 'stop', 'restart', 'redeploy']) {
184 component.daemonAction(action);
185 expect(component['daemonService'].action).toHaveBeenCalledWith(daemon.daemon_name, action);
186 }
187 });
188
189 it('should disable daemon actions', () => {
190 const daemon = {
191 daemon_type: 'osd',
192 status_desc: 'running'
193 };
194
195 const states = {
196 start: true,
197 stop: false,
198 restart: false,
199 redeploy: false
200 };
201 const expectBool = (toExpect: boolean, arg: boolean) => {
202 if (toExpect === true) {
203 expect(arg).toBeTruthy();
204 } else {
205 expect(arg).toBeFalsy();
206 }
207 };
208
209 component.selection.selected = [daemon];
210 for (const action of ['start', 'stop', 'restart', 'redeploy']) {
211 expectBool(states[action], component.actionDisabled(action));
212 }
213
214 daemon.status_desc = 'stopped';
215 states.start = false;
216 states.stop = true;
217 component.selection.selected = [daemon];
218 for (const action of ['start', 'stop', 'restart', 'redeploy']) {
219 expectBool(states[action], component.actionDisabled(action));
220 }
221 });
222
223 it('should disable daemon actions in mgr and mon daemon', () => {
224 const daemon = {
225 daemon_type: 'mgr',
226 status_desc: 'running'
227 };
228 for (const action of ['start', 'stop', 'restart', 'redeploy']) {
229 expect(component.actionDisabled(action)).toBeTruthy();
230 }
231 daemon.daemon_type = 'mon';
232 for (const action of ['start', 'stop', 'restart', 'redeploy']) {
233 expect(component.actionDisabled(action)).toBeTruthy();
234 }
235 });
236
237 it('should disable daemon actions if no selection', () => {
238 component.selection.selected = [];
239 for (const action of ['start', 'stop', 'restart', 'redeploy']) {
240 expect(component.actionDisabled(action)).toBeTruthy();
241 }
242 });
243
244 it('should sort daemons events', () => {
245 component.sortDaemonEvents();
246 const daemon = daemons[0];
247 for (let i = 1; i < daemon.events.length; i++) {
248 const t1 = new Date(daemon.events[i - 1].created).getTime();
249 const t2 = new Date(daemon.events[i].created).getTime();
250 expect(t1 >= t2).toBeTruthy();
251 }
252 });
253 });