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