]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.spec.ts
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / services / service-form / service-form.component.spec.ts
CommitLineData
adb31ebb
TL
1import { HttpClientTestingModule } from '@angular/common/http/testing';
2import { ComponentFixture, TestBed } from '@angular/core/testing';
3import { ReactiveFormsModule } from '@angular/forms';
522d829b 4import { By } from '@angular/platform-browser';
adb31ebb
TL
5import { RouterTestingModule } from '@angular/router/testing';
6
a4b75251 7import { NgbActiveModal, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
f67539c2 8import _ from 'lodash';
adb31ebb 9import { ToastrModule } from 'ngx-toastr';
39ae355f 10import { of } from 'rxjs';
adb31ebb 11
f67539c2 12import { CephServiceService } from '~/app/shared/api/ceph-service.service';
39ae355f 13import { PaginateObservable } from '~/app/shared/api/paginate.model';
f67539c2
TL
14import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
15import { SharedModule } from '~/app/shared/shared.module';
16import { configureTestBed, FormHelper } from '~/testing/unit-test-helper';
adb31ebb
TL
17import { ServiceFormComponent } from './service-form.component';
18
19describe('ServiceFormComponent', () => {
20 let component: ServiceFormComponent;
21 let fixture: ComponentFixture<ServiceFormComponent>;
22 let cephServiceService: CephServiceService;
23 let form: CdFormGroup;
24 let formHelper: FormHelper;
25
26 configureTestBed({
27 declarations: [ServiceFormComponent],
a4b75251 28 providers: [NgbActiveModal],
adb31ebb
TL
29 imports: [
30 HttpClientTestingModule,
f67539c2 31 NgbTypeaheadModule,
adb31ebb
TL
32 ReactiveFormsModule,
33 RouterTestingModule,
34 SharedModule,
35 ToastrModule.forRoot()
f67539c2 36 ]
adb31ebb
TL
37 });
38
39 beforeEach(() => {
40 fixture = TestBed.createComponent(ServiceFormComponent);
41 component = fixture.componentInstance;
a4b75251 42 component.ngOnInit();
adb31ebb
TL
43 form = component.serviceForm;
44 formHelper = new FormHelper(form);
45 fixture.detectChanges();
46 });
47
48 it('should create', () => {
49 expect(component).toBeTruthy();
50 });
51
52 describe('should test form', () => {
53 beforeEach(() => {
f67539c2 54 cephServiceService = TestBed.inject(CephServiceService);
adb31ebb
TL
55 spyOn(cephServiceService, 'create').and.stub();
56 });
57
58 it('should test placement (host)', () => {
59 formHelper.setValue('service_type', 'crash');
60 formHelper.setValue('placement', 'hosts');
61 formHelper.setValue('hosts', ['mgr0', 'mon0', 'osd0']);
62 formHelper.setValue('count', 2);
63 component.onSubmit();
64 expect(cephServiceService.create).toHaveBeenCalledWith({
65 service_type: 'crash',
66 placement: {
67 hosts: ['mgr0', 'mon0', 'osd0'],
68 count: 2
69 },
70 unmanaged: false
71 });
72 });
73
74 it('should test placement (label)', () => {
75 formHelper.setValue('service_type', 'mgr');
76 formHelper.setValue('placement', 'label');
77 formHelper.setValue('label', 'foo');
78 component.onSubmit();
79 expect(cephServiceService.create).toHaveBeenCalledWith({
80 service_type: 'mgr',
81 placement: {
82 label: 'foo'
83 },
84 unmanaged: false
85 });
86 });
87
88 it('should submit valid count', () => {
89 formHelper.setValue('count', 1);
90 component.onSubmit();
91 formHelper.expectValid('count');
92 });
93
94 it('should submit invalid count (1)', () => {
95 formHelper.setValue('count', 0);
96 component.onSubmit();
97 formHelper.expectError('count', 'min');
98 });
99
100 it('should submit invalid count (2)', () => {
101 formHelper.setValue('count', 'abc');
102 component.onSubmit();
103 formHelper.expectError('count', 'pattern');
104 });
105
106 it('should test unmanaged', () => {
522d829b
TL
107 formHelper.setValue('service_type', 'mgr');
108 formHelper.setValue('service_id', 'svc');
adb31ebb
TL
109 formHelper.setValue('placement', 'label');
110 formHelper.setValue('label', 'bar');
adb31ebb
TL
111 formHelper.setValue('unmanaged', true);
112 component.onSubmit();
113 expect(cephServiceService.create).toHaveBeenCalledWith({
522d829b
TL
114 service_type: 'mgr',
115 service_id: 'svc',
adb31ebb
TL
116 placement: {},
117 unmanaged: true
118 });
119 });
120
121 it('should test various services', () => {
122 _.forEach(
1e59de90 123 ['alertmanager', 'crash', 'mds', 'mgr', 'mon', 'node-exporter', 'prometheus', 'rbd-mirror'],
adb31ebb
TL
124 (serviceType) => {
125 formHelper.setValue('service_type', serviceType);
126 component.onSubmit();
127 expect(cephServiceService.create).toHaveBeenCalledWith({
128 service_type: serviceType,
129 placement: {},
130 unmanaged: false
131 });
132 }
133 );
134 });
1e59de90
TL
135
136 describe('should test service grafana', () => {
137 beforeEach(() => {
138 formHelper.setValue('service_type', 'grafana');
139 });
140
141 it('should sumbit grafana', () => {
142 component.onSubmit();
143 expect(cephServiceService.create).toHaveBeenCalledWith({
144 service_type: 'grafana',
145 placement: {},
146 unmanaged: false,
147 initial_admin_password: null,
148 port: null
149 });
150 });
151
152 it('should sumbit grafana with custom port and initial password', () => {
153 formHelper.setValue('grafana_port', 1234);
154 formHelper.setValue('grafana_admin_password', 'foo');
155 component.onSubmit();
156 expect(cephServiceService.create).toHaveBeenCalledWith({
157 service_type: 'grafana',
158 placement: {},
159 unmanaged: false,
160 initial_admin_password: 'foo',
161 port: 1234
162 });
163 });
164 });
adb31ebb
TL
165
166 describe('should test service nfs', () => {
167 beforeEach(() => {
168 formHelper.setValue('service_type', 'nfs');
adb31ebb
TL
169 });
170
a4b75251 171 it('should submit nfs', () => {
adb31ebb
TL
172 component.onSubmit();
173 expect(cephServiceService.create).toHaveBeenCalledWith({
174 service_type: 'nfs',
175 placement: {},
a4b75251 176 unmanaged: false
adb31ebb
TL
177 });
178 });
179 });
180
181 describe('should test service rgw', () => {
182 beforeEach(() => {
183 formHelper.setValue('service_type', 'rgw');
522d829b 184 formHelper.setValue('service_id', 'svc');
adb31ebb
TL
185 });
186
187 it('should test rgw valid service id', () => {
522d829b 188 formHelper.setValue('service_id', 'svc.realm.zone');
adb31ebb 189 formHelper.expectValid('service_id');
522d829b 190 formHelper.setValue('service_id', 'svc');
adb31ebb
TL
191 formHelper.expectValid('service_id');
192 });
193
194 it('should test rgw invalid service id', () => {
522d829b
TL
195 formHelper.setValue('service_id', '.');
196 formHelper.expectError('service_id', 'rgwPattern');
197 formHelper.setValue('service_id', 'svc.');
adb31ebb 198 formHelper.expectError('service_id', 'rgwPattern');
522d829b 199 formHelper.setValue('service_id', 'svc.realm');
adb31ebb 200 formHelper.expectError('service_id', 'rgwPattern');
522d829b 201 formHelper.setValue('service_id', 'svc.realm.');
adb31ebb 202 formHelper.expectError('service_id', 'rgwPattern');
522d829b
TL
203 formHelper.setValue('service_id', '.svc.realm');
204 formHelper.expectError('service_id', 'rgwPattern');
205 formHelper.setValue('service_id', 'svc.realm.zone.');
adb31ebb
TL
206 formHelper.expectError('service_id', 'rgwPattern');
207 });
208
522d829b
TL
209 it('should submit rgw with realm and zone', () => {
210 formHelper.setValue('service_id', 'svc.my-realm.my-zone');
211 component.onSubmit();
212 expect(cephServiceService.create).toHaveBeenCalledWith({
213 service_type: 'rgw',
214 service_id: 'svc',
215 rgw_realm: 'my-realm',
216 rgw_zone: 'my-zone',
217 placement: {},
218 unmanaged: false,
219 ssl: false
220 });
221 });
222
223 it('should submit rgw with port and ssl enabled', () => {
adb31ebb
TL
224 formHelper.setValue('rgw_frontend_port', 1234);
225 formHelper.setValue('ssl', true);
226 component.onSubmit();
227 expect(cephServiceService.create).toHaveBeenCalledWith({
228 service_type: 'rgw',
522d829b 229 service_id: 'svc',
adb31ebb
TL
230 placement: {},
231 unmanaged: false,
232 rgw_frontend_port: 1234,
233 rgw_frontend_ssl_certificate: '',
adb31ebb
TL
234 ssl: true
235 });
236 });
237
238 it('should submit valid rgw port (1)', () => {
239 formHelper.setValue('rgw_frontend_port', 1);
240 component.onSubmit();
241 formHelper.expectValid('rgw_frontend_port');
242 });
243
244 it('should submit valid rgw port (2)', () => {
245 formHelper.setValue('rgw_frontend_port', 65535);
246 component.onSubmit();
247 formHelper.expectValid('rgw_frontend_port');
248 });
249
250 it('should submit invalid rgw port (1)', () => {
251 formHelper.setValue('rgw_frontend_port', 0);
20effc67 252 fixture.detectChanges();
adb31ebb
TL
253 formHelper.expectError('rgw_frontend_port', 'min');
254 });
255
256 it('should submit invalid rgw port (2)', () => {
257 formHelper.setValue('rgw_frontend_port', 65536);
20effc67 258 fixture.detectChanges();
adb31ebb
TL
259 formHelper.expectError('rgw_frontend_port', 'max');
260 });
261
262 it('should submit invalid rgw port (3)', () => {
263 formHelper.setValue('rgw_frontend_port', 'abc');
264 component.onSubmit();
265 formHelper.expectError('rgw_frontend_port', 'pattern');
266 });
267
268 it('should submit rgw w/o port', () => {
269 formHelper.setValue('ssl', false);
270 component.onSubmit();
271 expect(cephServiceService.create).toHaveBeenCalledWith({
272 service_type: 'rgw',
522d829b 273 service_id: 'svc',
adb31ebb
TL
274 placement: {},
275 unmanaged: false,
276 ssl: false
277 });
278 });
522d829b
TL
279
280 it('should not show private key field', () => {
281 formHelper.setValue('ssl', true);
282 fixture.detectChanges();
283 const ssl_key = fixture.debugElement.query(By.css('#ssl_key'));
284 expect(ssl_key).toBeNull();
285 });
286
287 it('should test .pem file', () => {
288 const pemCert = `
289-----BEGIN CERTIFICATE-----
290iJ5IbgzlKPssdYwuAEI3yPZxX/g5vKBrgcyD3LttLL/DlElq/1xCnwVrv7WROSNu
291-----END CERTIFICATE-----
292-----BEGIN CERTIFICATE-----
293mn/S7BNBEC7AGe5ajmN+8hBTGdACUXe8rwMNrtTy/MwBZ0VpJsAAjJh+aptZh5yB
294-----END CERTIFICATE-----
295-----BEGIN RSA PRIVATE KEY-----
296x4Ea7kGVgx9kWh5XjWz9wjZvY49UKIT5ppIAWPMbLl3UpfckiuNhTA==
297-----END RSA PRIVATE KEY-----`;
298 formHelper.setValue('ssl', true);
299 formHelper.setValue('ssl_cert', pemCert);
300 fixture.detectChanges();
301 formHelper.expectValid('ssl_cert');
302 });
adb31ebb
TL
303 });
304
305 describe('should test service iscsi', () => {
306 beforeEach(() => {
307 formHelper.setValue('service_type', 'iscsi');
308 formHelper.setValue('pool', 'xyz');
309 formHelper.setValue('api_user', 'user');
310 formHelper.setValue('api_password', 'password');
311 formHelper.setValue('ssl', false);
312 });
313
314 it('should submit iscsi', () => {
315 component.onSubmit();
316 expect(cephServiceService.create).toHaveBeenCalledWith({
317 service_type: 'iscsi',
318 placement: {},
319 unmanaged: false,
320 pool: 'xyz',
321 api_user: 'user',
322 api_password: 'password',
323 api_secure: false
324 });
325 });
326
327 it('should submit iscsi with trusted ips', () => {
328 formHelper.setValue('ssl', true);
f67539c2 329 formHelper.setValue('trusted_ip_list', ' 172.16.0.5, 192.1.1.10 ');
adb31ebb
TL
330 component.onSubmit();
331 expect(cephServiceService.create).toHaveBeenCalledWith({
332 service_type: 'iscsi',
333 placement: {},
334 unmanaged: false,
335 pool: 'xyz',
336 api_user: 'user',
337 api_password: 'password',
338 api_secure: true,
339 ssl_cert: '',
340 ssl_key: '',
f67539c2 341 trusted_ip_list: '172.16.0.5, 192.1.1.10'
adb31ebb
TL
342 });
343 });
344
345 it('should submit iscsi with port', () => {
346 formHelper.setValue('api_port', 456);
347 component.onSubmit();
348 expect(cephServiceService.create).toHaveBeenCalledWith({
349 service_type: 'iscsi',
350 placement: {},
351 unmanaged: false,
352 pool: 'xyz',
353 api_user: 'user',
354 api_password: 'password',
355 api_secure: false,
356 api_port: 456
357 });
358 });
359
360 it('should submit valid iscsi port (1)', () => {
361 formHelper.setValue('api_port', 1);
362 component.onSubmit();
363 formHelper.expectValid('api_port');
364 });
365
366 it('should submit valid iscsi port (2)', () => {
367 formHelper.setValue('api_port', 65535);
368 component.onSubmit();
369 formHelper.expectValid('api_port');
370 });
371
372 it('should submit invalid iscsi port (1)', () => {
373 formHelper.setValue('api_port', 0);
20effc67 374 fixture.detectChanges();
adb31ebb
TL
375 formHelper.expectError('api_port', 'min');
376 });
377
378 it('should submit invalid iscsi port (2)', () => {
379 formHelper.setValue('api_port', 65536);
20effc67 380 fixture.detectChanges();
adb31ebb
TL
381 formHelper.expectError('api_port', 'max');
382 });
383
384 it('should submit invalid iscsi port (3)', () => {
385 formHelper.setValue('api_port', 'abc');
386 component.onSubmit();
387 formHelper.expectError('api_port', 'pattern');
388 });
20effc67
TL
389
390 it('should throw error when there is no pool', () => {
391 formHelper.expectErrorChange('pool', '', 'required');
392 });
adb31ebb 393 });
b3b6e05e
TL
394
395 describe('should test service ingress', () => {
396 beforeEach(() => {
397 formHelper.setValue('service_type', 'ingress');
398 formHelper.setValue('backend_service', 'rgw.foo');
399 formHelper.setValue('virtual_ip', '192.168.20.1/24');
400 formHelper.setValue('ssl', false);
401 });
402
403 it('should submit ingress', () => {
404 component.onSubmit();
405 expect(cephServiceService.create).toHaveBeenCalledWith({
406 service_type: 'ingress',
407 placement: {},
408 unmanaged: false,
409 backend_service: 'rgw.foo',
410 service_id: 'rgw.foo',
411 virtual_ip: '192.168.20.1/24',
412 virtual_interface_networks: null,
413 ssl: false
414 });
415 });
416
417 it('should pre-populate the service id', () => {
418 component.prePopulateId();
419 const prePopulatedID = component.serviceForm.getValue('service_id');
420 expect(prePopulatedID).toBe('rgw.foo');
421 });
422
423 it('should submit valid frontend and monitor port', () => {
424 // min value
425 formHelper.setValue('frontend_port', 1);
426 formHelper.setValue('monitor_port', 1);
20effc67 427 fixture.detectChanges();
b3b6e05e
TL
428 formHelper.expectValid('frontend_port');
429 formHelper.expectValid('monitor_port');
430
431 // max value
432 formHelper.setValue('frontend_port', 65535);
433 formHelper.setValue('monitor_port', 65535);
20effc67 434 fixture.detectChanges();
b3b6e05e
TL
435 formHelper.expectValid('frontend_port');
436 formHelper.expectValid('monitor_port');
437 });
438
439 it('should submit invalid frontend and monitor port', () => {
440 // min
441 formHelper.setValue('frontend_port', 0);
442 formHelper.setValue('monitor_port', 0);
20effc67 443 fixture.detectChanges();
b3b6e05e
TL
444 formHelper.expectError('frontend_port', 'min');
445 formHelper.expectError('monitor_port', 'min');
446
447 // max
448 formHelper.setValue('frontend_port', 65536);
449 formHelper.setValue('monitor_port', 65536);
20effc67 450 fixture.detectChanges();
b3b6e05e
TL
451 formHelper.expectError('frontend_port', 'max');
452 formHelper.expectError('monitor_port', 'max');
453
454 // pattern
455 formHelper.setValue('frontend_port', 'abc');
456 formHelper.setValue('monitor_port', 'abc');
457 component.onSubmit();
458 formHelper.expectError('frontend_port', 'pattern');
459 formHelper.expectError('monitor_port', 'pattern');
460 });
33c7a0ef
TL
461
462 it('should not show private key field with ssl enabled', () => {
463 formHelper.setValue('ssl', true);
464 fixture.detectChanges();
465 const ssl_key = fixture.debugElement.query(By.css('#ssl_key'));
466 expect(ssl_key).toBeNull();
467 });
468
469 it('should test .pem file with ssl enabled', () => {
470 const pemCert = `
471-----BEGIN CERTIFICATE-----
472iJ5IbgzlKPssdYwuAEI3yPZxX/g5vKBrgcyD3LttLL/DlElq/1xCnwVrv7WROSNu
473-----END CERTIFICATE-----
474-----BEGIN CERTIFICATE-----
475mn/S7BNBEC7AGe5ajmN+8hBTGdACUXe8rwMNrtTy/MwBZ0VpJsAAjJh+aptZh5yB
476-----END CERTIFICATE-----
477-----BEGIN RSA PRIVATE KEY-----
478x4Ea7kGVgx9kWh5XjWz9wjZvY49UKIT5ppIAWPMbLl3UpfckiuNhTA==
479-----END RSA PRIVATE KEY-----`;
480 formHelper.setValue('ssl', true);
481 formHelper.setValue('ssl_cert', pemCert);
482 fixture.detectChanges();
483 formHelper.expectValid('ssl_cert');
484 });
b3b6e05e 485 });
a4b75251 486
20effc67
TL
487 describe('should test service snmp-gateway', () => {
488 beforeEach(() => {
489 formHelper.setValue('service_type', 'snmp-gateway');
490 formHelper.setValue('snmp_destination', '192.168.20.1:8443');
491 });
492
493 it('should test snmp-gateway service with V2c', () => {
494 formHelper.setValue('snmp_version', 'V2c');
495 formHelper.setValue('snmp_community', 'public');
496 component.onSubmit();
497 expect(cephServiceService.create).toHaveBeenCalledWith({
498 service_type: 'snmp-gateway',
499 placement: {},
500 unmanaged: false,
501 snmp_version: 'V2c',
502 snmp_destination: '192.168.20.1:8443',
503 credentials: {
504 snmp_community: 'public'
505 }
506 });
507 });
508
509 it('should test snmp-gateway service with V3', () => {
510 formHelper.setValue('snmp_version', 'V3');
511 formHelper.setValue('engine_id', '800C53F00000');
512 formHelper.setValue('auth_protocol', 'SHA');
513 formHelper.setValue('privacy_protocol', 'DES');
514 formHelper.setValue('snmp_v3_auth_username', 'testuser');
515 formHelper.setValue('snmp_v3_auth_password', 'testpass');
516 formHelper.setValue('snmp_v3_priv_password', 'testencrypt');
517 component.onSubmit();
518 expect(cephServiceService.create).toHaveBeenCalledWith({
519 service_type: 'snmp-gateway',
520 placement: {},
521 unmanaged: false,
522 snmp_version: 'V3',
523 snmp_destination: '192.168.20.1:8443',
524 engine_id: '800C53F00000',
525 auth_protocol: 'SHA',
526 privacy_protocol: 'DES',
527 credentials: {
528 snmp_v3_auth_username: 'testuser',
529 snmp_v3_auth_password: 'testpass',
530 snmp_v3_priv_password: 'testencrypt'
531 }
532 });
533 });
534
535 it('should submit invalid snmp destination', () => {
536 formHelper.setValue('snmp_version', 'V2c');
537 formHelper.setValue('snmp_destination', '192.168.20.1');
538 formHelper.setValue('snmp_community', 'public');
539 formHelper.expectError('snmp_destination', 'snmpDestinationPattern');
540 });
541
542 it('should submit invalid snmp engine id', () => {
543 formHelper.setValue('snmp_version', 'V3');
544 formHelper.setValue('snmp_destination', '192.168.20.1');
545 formHelper.setValue('engine_id', 'AABBCCDDE');
546 formHelper.setValue('auth_protocol', 'SHA');
547 formHelper.setValue('privacy_protocol', 'DES');
548 formHelper.setValue('snmp_v3_auth_username', 'testuser');
549 formHelper.setValue('snmp_v3_auth_password', 'testpass');
550
551 formHelper.expectError('engine_id', 'snmpEngineIdPattern');
552 });
553 });
554
39ae355f
TL
555 describe('should test service mds', () => {
556 beforeEach(() => {
557 formHelper.setValue('service_type', 'mds');
558 const paginate_obs = new PaginateObservable<any>(of({}));
559 spyOn(cephServiceService, 'list').and.returnValue(paginate_obs);
560 });
561
562 it('should test mds valid service id', () => {
563 formHelper.setValue('service_id', 'svc123');
564 formHelper.expectValid('service_id');
565 formHelper.setValue('service_id', 'svc_id-1');
566 formHelper.expectValid('service_id');
567 });
568
569 it('should test mds invalid service id', () => {
570 formHelper.setValue('service_id', '123');
571 formHelper.expectError('service_id', 'mdsPattern');
572 formHelper.setValue('service_id', '123svc');
573 formHelper.expectError('service_id', 'mdsPattern');
574 formHelper.setValue('service_id', 'svc#1');
575 formHelper.expectError('service_id', 'mdsPattern');
576 });
577 });
578
a4b75251
TL
579 describe('check edit fields', () => {
580 beforeEach(() => {
581 component.editing = true;
582 });
583
584 it('should check whether edit field is correctly loaded', () => {
39ae355f
TL
585 const paginate_obs = new PaginateObservable<any>(of({}));
586 const cephServiceSpy = spyOn(cephServiceService, 'list').and.returnValue(paginate_obs);
a4b75251
TL
587 component.ngOnInit();
588 expect(cephServiceSpy).toBeCalledTimes(2);
589 expect(component.action).toBe('Edit');
590 const serviceType = fixture.debugElement.query(By.css('#service_type')).nativeElement;
591 const serviceId = fixture.debugElement.query(By.css('#service_id')).nativeElement;
592 expect(serviceType.disabled).toBeTruthy();
593 expect(serviceId.disabled).toBeTruthy();
594 });
595 });
adb31ebb
TL
596 });
597});