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';
7 import { NgbActiveModal, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
8 import _ from 'lodash';
9 import { ToastrModule } from 'ngx-toastr';
10 import { of } from 'rxjs';
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';
19 describe('ServiceFormComponent', () => {
20 let component: ServiceFormComponent;
21 let fixture: ComponentFixture<ServiceFormComponent>;
22 let cephServiceService: CephServiceService;
23 let form: CdFormGroup;
24 let formHelper: FormHelper;
27 declarations: [ServiceFormComponent],
28 providers: [NgbActiveModal],
30 HttpClientTestingModule,
35 ToastrModule.forRoot()
40 fixture = TestBed.createComponent(ServiceFormComponent);
41 component = fixture.componentInstance;
43 form = component.serviceForm;
44 formHelper = new FormHelper(form);
45 fixture.detectChanges();
48 it('should create', () => {
49 expect(component).toBeTruthy();
52 describe('should test form', () => {
54 cephServiceService = TestBed.inject(CephServiceService);
55 spyOn(cephServiceService, 'create').and.stub();
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);
64 expect(cephServiceService.create).toHaveBeenCalledWith({
65 service_type: 'crash',
67 hosts: ['mgr0', 'mon0', 'osd0'],
74 it('should test placement (label)', () => {
75 formHelper.setValue('service_type', 'mgr');
76 formHelper.setValue('placement', 'label');
77 formHelper.setValue('label', 'foo');
79 expect(cephServiceService.create).toHaveBeenCalledWith({
88 it('should submit valid count', () => {
89 formHelper.setValue('count', 1);
91 formHelper.expectValid('count');
94 it('should submit invalid count (1)', () => {
95 formHelper.setValue('count', 0);
97 formHelper.expectError('count', 'min');
100 it('should submit invalid count (2)', () => {
101 formHelper.setValue('count', 'abc');
102 component.onSubmit();
103 formHelper.expectError('count', 'pattern');
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({
121 it('should test various services', () => {
123 ['alertmanager', 'crash', 'mds', 'mgr', 'mon', 'node-exporter', 'prometheus', 'rbd-mirror'],
125 formHelper.setValue('service_type', serviceType);
126 component.onSubmit();
127 expect(cephServiceService.create).toHaveBeenCalledWith({
128 service_type: serviceType,
136 describe('should test service grafana', () => {
138 formHelper.setValue('service_type', 'grafana');
141 it('should sumbit grafana', () => {
142 component.onSubmit();
143 expect(cephServiceService.create).toHaveBeenCalledWith({
144 service_type: 'grafana',
147 initial_admin_password: null,
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',
160 initial_admin_password: 'foo',
166 describe('should test service nfs', () => {
168 formHelper.setValue('service_type', 'nfs');
171 it('should submit nfs', () => {
172 component.onSubmit();
173 expect(cephServiceService.create).toHaveBeenCalledWith({
181 describe('should test service rgw', () => {
183 formHelper.setValue('service_type', 'rgw');
184 formHelper.setValue('service_id', 'svc');
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');
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({
203 rgw_realm: 'my-realm',
205 rgw_zonegroup: 'my-zonegroup',
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({
224 rgw_frontend_port: 1234,
225 rgw_frontend_ssl_certificate: '',
230 it('should submit valid rgw port (1)', () => {
231 formHelper.setValue('rgw_frontend_port', 1);
232 component.onSubmit();
233 formHelper.expectValid('rgw_frontend_port');
236 it('should submit valid rgw port (2)', () => {
237 formHelper.setValue('rgw_frontend_port', 65535);
238 component.onSubmit();
239 formHelper.expectValid('rgw_frontend_port');
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');
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');
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');
260 it('should submit rgw w/o port', () => {
261 formHelper.setValue('ssl', false);
262 component.onSubmit();
263 expect(cephServiceService.create).toHaveBeenCalledWith({
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();
282 it('should test .pem file', () => {
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');
300 describe('should test service iscsi', () => {
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);
309 it('should submit iscsi', () => {
310 component.onSubmit();
311 expect(cephServiceService.create).toHaveBeenCalledWith({
312 service_type: 'iscsi',
317 api_password: 'password',
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',
332 api_password: 'password',
336 trusted_ip_list: '172.16.0.5, 192.1.1.10'
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',
349 api_password: 'password',
355 it('should submit valid iscsi port (1)', () => {
356 formHelper.setValue('api_port', 1);
357 component.onSubmit();
358 formHelper.expectValid('api_port');
361 it('should submit valid iscsi port (2)', () => {
362 formHelper.setValue('api_port', 65535);
363 component.onSubmit();
364 formHelper.expectValid('api_port');
367 it('should submit invalid iscsi port (1)', () => {
368 formHelper.setValue('api_port', 0);
369 fixture.detectChanges();
370 formHelper.expectError('api_port', 'min');
373 it('should submit invalid iscsi port (2)', () => {
374 formHelper.setValue('api_port', 65536);
375 fixture.detectChanges();
376 formHelper.expectError('api_port', 'max');
379 it('should submit invalid iscsi port (3)', () => {
380 formHelper.setValue('api_port', 'abc');
381 component.onSubmit();
382 formHelper.expectError('api_port', 'pattern');
385 it('should throw error when there is no pool', () => {
386 formHelper.expectErrorChange('pool', '', 'required');
390 describe('should test service nvmeof', () => {
392 formHelper.setValue('service_type', 'nvmeof');
393 formHelper.setValue('service_id', 'svc');
394 formHelper.setValue('pool', 'xyz');
397 it('should submit nvmeof', () => {
398 component.onSubmit();
399 expect(cephServiceService.create).toHaveBeenCalledWith({
400 service_type: 'nvmeof',
408 it('should throw error when there is no service id', () => {
409 formHelper.expectErrorChange('service_id', '', 'required');
412 it('should throw error when there is no pool', () => {
413 formHelper.expectErrorChange('pool', '', 'required');
417 describe('should test service smb', () => {
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');
425 it('should submit smb', () => {
426 component.onSubmit();
427 expect(cephServiceService.create).toHaveBeenCalledWith({
432 cluster_id: 'cluster_foo',
433 config_uri: 'rados://.smb/foo/scc.toml'
438 describe('should test service ingress', () => {
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);
446 it('should submit ingress', () => {
447 component.onSubmit();
448 expect(cephServiceService.create).toHaveBeenCalledWith({
449 service_type: 'ingress',
452 backend_service: 'rgw.foo',
453 service_id: 'rgw.foo',
454 virtual_ip: '192.168.20.1/24',
455 virtual_interface_networks: null,
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');
466 it('should submit valid frontend and monitor port', () => {
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');
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');
482 it('should submit invalid frontend and monitor port', () => {
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');
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');
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');
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();
512 it('should test .pem file with ssl enabled', () => {
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');
530 describe('should test service snmp-gateway', () => {
532 formHelper.setValue('service_type', 'snmp-gateway');
533 formHelper.setValue('snmp_destination', '192.168.20.1:8443');
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',
545 snmp_destination: '192.168.20.1:8443',
547 snmp_community: 'public'
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',
566 snmp_destination: '192.168.20.1:8443',
567 engine_id: '800C53F00000',
568 auth_protocol: 'SHA',
569 privacy_protocol: 'DES',
571 snmp_v3_auth_username: 'testuser',
572 snmp_v3_auth_password: 'testpass',
573 snmp_v3_priv_password: 'testencrypt'
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');
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');
594 formHelper.expectError('engine_id', 'snmpEngineIdPattern');
598 describe('should test service mds', () => {
600 formHelper.setValue('service_type', 'mds');
601 const paginate_obs = new PaginateObservable<any>(of({}));
602 spyOn(cephServiceService, 'list').and.returnValue(paginate_obs);
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');
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');
622 describe('check edit fields', () => {
624 component.editing = true;
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();
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();