]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
db1e7851c2e4adc44b12f82db6d1498f9f45e1b9
[ceph-ci.git] /
1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { ComponentFixture, TestBed } from '@angular/core/testing';
3 import { ReactiveFormsModule } from '@angular/forms';
4 import { By } from '@angular/platform-browser';
5 import { RouterTestingModule } from '@angular/router/testing';
6
7 import { NgbActiveModal, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
8 import _ from 'lodash';
9 import { ToastrModule } from 'ngx-toastr';
10 import { of } from 'rxjs';
11
12 import { CephServiceService } from '~/app/shared/api/ceph-service.service';
13 import { PaginateObservable } from '~/app/shared/api/paginate.model';
14 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
15 import { SharedModule } from '~/app/shared/shared.module';
16 import { configureTestBed, FormHelper } from '~/testing/unit-test-helper';
17 import { ServiceFormComponent } from './service-form.component';
18
19 describe('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],
28     providers: [NgbActiveModal],
29     imports: [
30       HttpClientTestingModule,
31       NgbTypeaheadModule,
32       ReactiveFormsModule,
33       RouterTestingModule,
34       SharedModule,
35       ToastrModule.forRoot()
36     ]
37   });
38
39   beforeEach(() => {
40     fixture = TestBed.createComponent(ServiceFormComponent);
41     component = fixture.componentInstance;
42     component.ngOnInit();
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(() => {
54       cephServiceService = TestBed.inject(CephServiceService);
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', () => {
107       formHelper.setValue('service_type', 'mgr');
108       formHelper.setValue('service_id', 'svc');
109       formHelper.setValue('placement', 'label');
110       formHelper.setValue('label', 'bar');
111       formHelper.setValue('unmanaged', true);
112       component.onSubmit();
113       expect(cephServiceService.create).toHaveBeenCalledWith({
114         service_type: 'mgr',
115         service_id: 'svc',
116         placement: {},
117         unmanaged: true
118       });
119     });
120
121     it('should test various services', () => {
122       _.forEach(
123         ['alertmanager', 'crash', 'mds', 'mgr', 'mon', 'node-exporter', 'prometheus', 'rbd-mirror'],
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     });
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     });
165
166     describe('should test service nfs', () => {
167       beforeEach(() => {
168         formHelper.setValue('service_type', 'nfs');
169       });
170
171       it('should submit nfs', () => {
172         component.onSubmit();
173         expect(cephServiceService.create).toHaveBeenCalledWith({
174           service_type: 'nfs',
175           placement: {},
176           unmanaged: false
177         });
178       });
179     });
180
181     describe('should test service rgw', () => {
182       beforeEach(() => {
183         formHelper.setValue('service_type', 'rgw');
184         formHelper.setValue('service_id', 'svc');
185       });
186
187       it('should test rgw valid service id', () => {
188         formHelper.setValue('service_id', 'svc.realm.zone');
189         formHelper.expectValid('service_id');
190         formHelper.setValue('service_id', 'svc');
191         formHelper.expectValid('service_id');
192       });
193
194       it('should submit rgw with realm, zonegroup and zone', () => {
195         formHelper.setValue('service_id', 'svc');
196         formHelper.setValue('realm_name', 'my-realm');
197         formHelper.setValue('zone_name', 'my-zone');
198         formHelper.setValue('zonegroup_name', 'my-zonegroup');
199         component.onSubmit();
200         expect(cephServiceService.create).toHaveBeenCalledWith({
201           service_type: 'rgw',
202           service_id: 'svc',
203           rgw_realm: 'my-realm',
204           rgw_zone: 'my-zone',
205           rgw_zonegroup: 'my-zonegroup',
206           placement: {},
207           unmanaged: false,
208           ssl: false
209         });
210       });
211
212       it('should submit rgw with port and ssl enabled', () => {
213         formHelper.setValue('rgw_frontend_port', 1234);
214         formHelper.setValue('ssl', true);
215         component.onSubmit();
216         expect(cephServiceService.create).toHaveBeenCalledWith({
217           service_type: 'rgw',
218           service_id: 'svc',
219           rgw_realm: null,
220           rgw_zone: null,
221           rgw_zonegroup: null,
222           placement: {},
223           unmanaged: false,
224           rgw_frontend_port: 1234,
225           rgw_frontend_ssl_certificate: '',
226           ssl: true
227         });
228       });
229
230       it('should submit valid rgw port (1)', () => {
231         formHelper.setValue('rgw_frontend_port', 1);
232         component.onSubmit();
233         formHelper.expectValid('rgw_frontend_port');
234       });
235
236       it('should submit valid rgw port (2)', () => {
237         formHelper.setValue('rgw_frontend_port', 65535);
238         component.onSubmit();
239         formHelper.expectValid('rgw_frontend_port');
240       });
241
242       it('should submit invalid rgw port (1)', () => {
243         formHelper.setValue('rgw_frontend_port', 0);
244         fixture.detectChanges();
245         formHelper.expectError('rgw_frontend_port', 'min');
246       });
247
248       it('should submit invalid rgw port (2)', () => {
249         formHelper.setValue('rgw_frontend_port', 65536);
250         fixture.detectChanges();
251         formHelper.expectError('rgw_frontend_port', 'max');
252       });
253
254       it('should submit invalid rgw port (3)', () => {
255         formHelper.setValue('rgw_frontend_port', 'abc');
256         component.onSubmit();
257         formHelper.expectError('rgw_frontend_port', 'pattern');
258       });
259
260       it('should submit rgw w/o port', () => {
261         formHelper.setValue('ssl', false);
262         component.onSubmit();
263         expect(cephServiceService.create).toHaveBeenCalledWith({
264           service_type: 'rgw',
265           service_id: 'svc',
266           rgw_realm: null,
267           rgw_zone: null,
268           rgw_zonegroup: null,
269           placement: {},
270           unmanaged: false,
271           ssl: false
272         });
273       });
274
275       it('should not show private key field', () => {
276         formHelper.setValue('ssl', true);
277         fixture.detectChanges();
278         const ssl_key = fixture.debugElement.query(By.css('#ssl_key'));
279         expect(ssl_key).toBeNull();
280       });
281
282       it('should test .pem file', () => {
283         const pemCert = `
284 -----BEGIN CERTIFICATE-----
285 iJ5IbgzlKPssdYwuAEI3yPZxX/g5vKBrgcyD3LttLL/DlElq/1xCnwVrv7WROSNu
286 -----END CERTIFICATE-----
287 -----BEGIN CERTIFICATE-----
288 mn/S7BNBEC7AGe5ajmN+8hBTGdACUXe8rwMNrtTy/MwBZ0VpJsAAjJh+aptZh5yB
289 -----END CERTIFICATE-----
290 -----BEGIN RSA PRIVATE KEY-----
291 x4Ea7kGVgx9kWh5XjWz9wjZvY49UKIT5ppIAWPMbLl3UpfckiuNhTA==
292 -----END RSA PRIVATE KEY-----`;
293         formHelper.setValue('ssl', true);
294         formHelper.setValue('ssl_cert', pemCert);
295         fixture.detectChanges();
296         formHelper.expectValid('ssl_cert');
297       });
298     });
299
300     describe('should test service iscsi', () => {
301       beforeEach(() => {
302         formHelper.setValue('service_type', 'iscsi');
303         formHelper.setValue('pool', 'xyz');
304         formHelper.setValue('api_user', 'user');
305         formHelper.setValue('api_password', 'password');
306         formHelper.setValue('ssl', false);
307       });
308
309       it('should submit iscsi', () => {
310         component.onSubmit();
311         expect(cephServiceService.create).toHaveBeenCalledWith({
312           service_type: 'iscsi',
313           placement: {},
314           unmanaged: false,
315           pool: 'xyz',
316           api_user: 'user',
317           api_password: 'password',
318           api_secure: false
319         });
320       });
321
322       it('should submit iscsi with trusted ips', () => {
323         formHelper.setValue('ssl', true);
324         formHelper.setValue('trusted_ip_list', ' 172.16.0.5, 192.1.1.10  ');
325         component.onSubmit();
326         expect(cephServiceService.create).toHaveBeenCalledWith({
327           service_type: 'iscsi',
328           placement: {},
329           unmanaged: false,
330           pool: 'xyz',
331           api_user: 'user',
332           api_password: 'password',
333           api_secure: true,
334           ssl_cert: '',
335           ssl_key: '',
336           trusted_ip_list: '172.16.0.5, 192.1.1.10'
337         });
338       });
339
340       it('should submit iscsi with port', () => {
341         formHelper.setValue('api_port', 456);
342         component.onSubmit();
343         expect(cephServiceService.create).toHaveBeenCalledWith({
344           service_type: 'iscsi',
345           placement: {},
346           unmanaged: false,
347           pool: 'xyz',
348           api_user: 'user',
349           api_password: 'password',
350           api_secure: false,
351           api_port: 456
352         });
353       });
354
355       it('should submit valid iscsi port (1)', () => {
356         formHelper.setValue('api_port', 1);
357         component.onSubmit();
358         formHelper.expectValid('api_port');
359       });
360
361       it('should submit valid iscsi port (2)', () => {
362         formHelper.setValue('api_port', 65535);
363         component.onSubmit();
364         formHelper.expectValid('api_port');
365       });
366
367       it('should submit invalid iscsi port (1)', () => {
368         formHelper.setValue('api_port', 0);
369         fixture.detectChanges();
370         formHelper.expectError('api_port', 'min');
371       });
372
373       it('should submit invalid iscsi port (2)', () => {
374         formHelper.setValue('api_port', 65536);
375         fixture.detectChanges();
376         formHelper.expectError('api_port', 'max');
377       });
378
379       it('should submit invalid iscsi port (3)', () => {
380         formHelper.setValue('api_port', 'abc');
381         component.onSubmit();
382         formHelper.expectError('api_port', 'pattern');
383       });
384
385       it('should throw error when there is no pool', () => {
386         formHelper.expectErrorChange('pool', '', 'required');
387       });
388     });
389
390     describe('should test service nvmeof', () => {
391       beforeEach(() => {
392         formHelper.setValue('service_type', 'nvmeof');
393         formHelper.setValue('service_id', 'svc');
394         formHelper.setValue('pool', 'xyz');
395       });
396
397       it('should submit nvmeof', () => {
398         component.onSubmit();
399         expect(cephServiceService.create).toHaveBeenCalledWith({
400           service_type: 'nvmeof',
401           service_id: 'svc',
402           placement: {},
403           unmanaged: false,
404           pool: 'xyz'
405         });
406       });
407
408       it('should throw error when there is no service id', () => {
409         formHelper.expectErrorChange('service_id', '', 'required');
410       });
411
412       it('should throw error when there is no pool', () => {
413         formHelper.expectErrorChange('pool', '', 'required');
414       });
415     });
416
417     describe('should test service smb', () => {
418       beforeEach(() => {
419         formHelper.setValue('service_type', 'smb');
420         formHelper.setValue('service_id', 'foo');
421         formHelper.setValue('cluster_id', 'cluster_foo');
422         formHelper.setValue('config_uri', 'rados://.smb/foo/scc.toml');
423       });
424
425       it('should submit smb', () => {
426         component.onSubmit();
427         expect(cephServiceService.create).toHaveBeenCalledWith({
428           service_type: 'smb',
429           placement: {},
430           unmanaged: false,
431           service_id: 'foo',
432           cluster_id: 'cluster_foo',
433           config_uri: 'rados://.smb/foo/scc.toml'
434         });
435       });
436     });
437
438     describe('should test service ingress', () => {
439       beforeEach(() => {
440         formHelper.setValue('service_type', 'ingress');
441         formHelper.setValue('backend_service', 'rgw.foo');
442         formHelper.setValue('virtual_ip', '192.168.20.1/24');
443         formHelper.setValue('ssl', false);
444       });
445
446       it('should submit ingress', () => {
447         component.onSubmit();
448         expect(cephServiceService.create).toHaveBeenCalledWith({
449           service_type: 'ingress',
450           placement: {},
451           unmanaged: false,
452           backend_service: 'rgw.foo',
453           service_id: 'rgw.foo',
454           virtual_ip: '192.168.20.1/24',
455           virtual_interface_networks: null,
456           ssl: false
457         });
458       });
459
460       it('should pre-populate the service id', () => {
461         component.prePopulateId();
462         const prePopulatedID = component.serviceForm.getValue('service_id');
463         expect(prePopulatedID).toBe('rgw.foo');
464       });
465
466       it('should submit valid frontend and monitor port', () => {
467         // min value
468         formHelper.setValue('frontend_port', 1);
469         formHelper.setValue('monitor_port', 1);
470         fixture.detectChanges();
471         formHelper.expectValid('frontend_port');
472         formHelper.expectValid('monitor_port');
473
474         // max value
475         formHelper.setValue('frontend_port', 65535);
476         formHelper.setValue('monitor_port', 65535);
477         fixture.detectChanges();
478         formHelper.expectValid('frontend_port');
479         formHelper.expectValid('monitor_port');
480       });
481
482       it('should submit invalid frontend and monitor port', () => {
483         // min
484         formHelper.setValue('frontend_port', 0);
485         formHelper.setValue('monitor_port', 0);
486         fixture.detectChanges();
487         formHelper.expectError('frontend_port', 'min');
488         formHelper.expectError('monitor_port', 'min');
489
490         // max
491         formHelper.setValue('frontend_port', 65536);
492         formHelper.setValue('monitor_port', 65536);
493         fixture.detectChanges();
494         formHelper.expectError('frontend_port', 'max');
495         formHelper.expectError('monitor_port', 'max');
496
497         // pattern
498         formHelper.setValue('frontend_port', 'abc');
499         formHelper.setValue('monitor_port', 'abc');
500         component.onSubmit();
501         formHelper.expectError('frontend_port', 'pattern');
502         formHelper.expectError('monitor_port', 'pattern');
503       });
504
505       it('should not show private key field with ssl enabled', () => {
506         formHelper.setValue('ssl', true);
507         fixture.detectChanges();
508         const ssl_key = fixture.debugElement.query(By.css('#ssl_key'));
509         expect(ssl_key).toBeNull();
510       });
511
512       it('should test .pem file with ssl enabled', () => {
513         const pemCert = `
514 -----BEGIN CERTIFICATE-----
515 iJ5IbgzlKPssdYwuAEI3yPZxX/g5vKBrgcyD3LttLL/DlElq/1xCnwVrv7WROSNu
516 -----END CERTIFICATE-----
517 -----BEGIN CERTIFICATE-----
518 mn/S7BNBEC7AGe5ajmN+8hBTGdACUXe8rwMNrtTy/MwBZ0VpJsAAjJh+aptZh5yB
519 -----END CERTIFICATE-----
520 -----BEGIN RSA PRIVATE KEY-----
521 x4Ea7kGVgx9kWh5XjWz9wjZvY49UKIT5ppIAWPMbLl3UpfckiuNhTA==
522 -----END RSA PRIVATE KEY-----`;
523         formHelper.setValue('ssl', true);
524         formHelper.setValue('ssl_cert', pemCert);
525         fixture.detectChanges();
526         formHelper.expectValid('ssl_cert');
527       });
528     });
529
530     describe('should test service snmp-gateway', () => {
531       beforeEach(() => {
532         formHelper.setValue('service_type', 'snmp-gateway');
533         formHelper.setValue('snmp_destination', '192.168.20.1:8443');
534       });
535
536       it('should test snmp-gateway service with V2c', () => {
537         formHelper.setValue('snmp_version', 'V2c');
538         formHelper.setValue('snmp_community', 'public');
539         component.onSubmit();
540         expect(cephServiceService.create).toHaveBeenCalledWith({
541           service_type: 'snmp-gateway',
542           placement: {},
543           unmanaged: false,
544           snmp_version: 'V2c',
545           snmp_destination: '192.168.20.1:8443',
546           credentials: {
547             snmp_community: 'public'
548           }
549         });
550       });
551
552       it('should test snmp-gateway service with V3', () => {
553         formHelper.setValue('snmp_version', 'V3');
554         formHelper.setValue('engine_id', '800C53F00000');
555         formHelper.setValue('auth_protocol', 'SHA');
556         formHelper.setValue('privacy_protocol', 'DES');
557         formHelper.setValue('snmp_v3_auth_username', 'testuser');
558         formHelper.setValue('snmp_v3_auth_password', 'testpass');
559         formHelper.setValue('snmp_v3_priv_password', 'testencrypt');
560         component.onSubmit();
561         expect(cephServiceService.create).toHaveBeenCalledWith({
562           service_type: 'snmp-gateway',
563           placement: {},
564           unmanaged: false,
565           snmp_version: 'V3',
566           snmp_destination: '192.168.20.1:8443',
567           engine_id: '800C53F00000',
568           auth_protocol: 'SHA',
569           privacy_protocol: 'DES',
570           credentials: {
571             snmp_v3_auth_username: 'testuser',
572             snmp_v3_auth_password: 'testpass',
573             snmp_v3_priv_password: 'testencrypt'
574           }
575         });
576       });
577
578       it('should submit invalid snmp destination', () => {
579         formHelper.setValue('snmp_version', 'V2c');
580         formHelper.setValue('snmp_destination', '192.168.20.1');
581         formHelper.setValue('snmp_community', 'public');
582         formHelper.expectError('snmp_destination', 'snmpDestinationPattern');
583       });
584
585       it('should submit invalid snmp engine id', () => {
586         formHelper.setValue('snmp_version', 'V3');
587         formHelper.setValue('snmp_destination', '192.168.20.1');
588         formHelper.setValue('engine_id', 'AABBCCDDE');
589         formHelper.setValue('auth_protocol', 'SHA');
590         formHelper.setValue('privacy_protocol', 'DES');
591         formHelper.setValue('snmp_v3_auth_username', 'testuser');
592         formHelper.setValue('snmp_v3_auth_password', 'testpass');
593
594         formHelper.expectError('engine_id', 'snmpEngineIdPattern');
595       });
596     });
597
598     describe('should test service mds', () => {
599       beforeEach(() => {
600         formHelper.setValue('service_type', 'mds');
601         const paginate_obs = new PaginateObservable<any>(of({}));
602         spyOn(cephServiceService, 'list').and.returnValue(paginate_obs);
603       });
604
605       it('should test mds valid service id', () => {
606         formHelper.setValue('service_id', 'svc123');
607         formHelper.expectValid('service_id');
608         formHelper.setValue('service_id', 'svc_id-1');
609         formHelper.expectValid('service_id');
610       });
611
612       it('should test mds invalid service id', () => {
613         formHelper.setValue('service_id', '123');
614         formHelper.expectError('service_id', 'mdsPattern');
615         formHelper.setValue('service_id', '123svc');
616         formHelper.expectError('service_id', 'mdsPattern');
617         formHelper.setValue('service_id', 'svc#1');
618         formHelper.expectError('service_id', 'mdsPattern');
619       });
620     });
621
622     describe('check edit fields', () => {
623       beforeEach(() => {
624         component.editing = true;
625       });
626
627       it('should check whether edit field is correctly loaded', () => {
628         const paginate_obs = new PaginateObservable<any>(of({}));
629         const cephServiceSpy = spyOn(cephServiceService, 'list').and.returnValue(paginate_obs);
630         component.ngOnInit();
631         expect(cephServiceSpy).toBeCalledTimes(2);
632         expect(component.action).toBe('Edit');
633         const serviceType = fixture.debugElement.query(By.css('#service_type')).nativeElement;
634         const serviceId = fixture.debugElement.query(By.css('#service_id')).nativeElement;
635         expect(serviceType.disabled).toBeTruthy();
636         expect(serviceId.disabled).toBeTruthy();
637       });
638
639       it('should not edit pools for nvmeof service', () => {
640         component.serviceType = 'nvmeof';
641         formHelper.setValue('service_type', 'nvmeof');
642         component.ngOnInit();
643         fixture.detectChanges();
644         const poolId = fixture.debugElement.query(By.css('#pool')).nativeElement;
645         expect(poolId.disabled).toBeTruthy();
646       });
647     });
648   });
649 });