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