]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/blob
481cf9ddce6516111547393f23237d50b7e2b1b8
[ceph-ci.git] /
1 import { Component, EventEmitter, OnDestroy, OnInit, Output } from '@angular/core';
2 import { AbstractControl, FormControl, Validators } from '@angular/forms';
3 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 import _ from 'lodash';
5 import { Subscription } from 'rxjs';
6 import { MultiClusterService } from '~/app/shared/api/multi-cluster.service';
7 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
8 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
9 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
10 import { CdValidators } from '~/app/shared/forms/cd-validators';
11 import { MultiCluster } from '~/app/shared/models/multi-cluster';
12 import { NotificationService } from '~/app/shared/services/notification.service';
13
14 @Component({
15   selector: 'cd-multi-cluster-form',
16   templateUrl: './multi-cluster-form.component.html',
17   styleUrls: ['./multi-cluster-form.component.scss']
18 })
19 export class MultiClusterFormComponent implements OnInit, OnDestroy {
20   @Output()
21   submitAction = new EventEmitter();
22   clusterApiUrlCmd = 'ceph mgr services';
23   remoteClusterForm: CdFormGroup;
24   connectionVerified: boolean;
25   connectionMessage = '';
26   private subs = new Subscription();
27   action: string;
28   cluster: MultiCluster;
29   clustersData: MultiCluster[];
30   clusterAliasNames: string[];
31   clusterUrls: string[];
32   clusterUsers: string[];
33   clusterUrlUserMap: Map<string, string>;
34   hubUrl: string;
35
36   constructor(
37     public activeModal: NgbActiveModal,
38     public actionLabels: ActionLabelsI18n,
39     public notificationService: NotificationService,
40     private multiClusterService: MultiClusterService
41   ) {
42     this.subs.add(
43       this.multiClusterService.subscribe((resp: any) => {
44         this.hubUrl = resp['hub_url'];
45       })
46     );
47     this.createForm();
48   }
49   ngOnInit(): void {
50     if (this.action === 'edit') {
51       this.remoteClusterForm.get('remoteClusterUrl').setValue(this.cluster.url);
52       this.remoteClusterForm.get('clusterAlias').setValue(this.cluster.cluster_alias);
53       this.remoteClusterForm.get('ssl').setValue(this.cluster.ssl_verify);
54       this.remoteClusterForm.get('ssl_cert').setValue(this.cluster.ssl_certificate);
55     }
56     if (this.action === 'reconnect') {
57       this.remoteClusterForm.get('remoteClusterUrl').setValue(this.cluster.url);
58       this.remoteClusterForm.get('remoteClusterUrl').disable();
59       this.remoteClusterForm.get('clusterAlias').setValue(this.cluster.cluster_alias);
60       this.remoteClusterForm.get('clusterAlias').disable();
61       this.remoteClusterForm.get('username').setValue(this.cluster.user);
62       this.remoteClusterForm.get('username').disable();
63       this.remoteClusterForm.get('ssl').setValue(this.cluster.ssl_verify);
64       this.remoteClusterForm.get('ssl_cert').setValue(this.cluster.ssl_certificate);
65     }
66     [this.clusterAliasNames, this.clusterUrls, this.clusterUsers] = [
67       'cluster_alias',
68       'url',
69       'user'
70     ].map((prop) => this.clustersData?.map((cluster) => cluster[prop]));
71   }
72
73   createForm() {
74     this.remoteClusterForm = new CdFormGroup({
75       username: new FormControl('', [
76         CdValidators.custom('uniqueUrlandUser', (username: string) => {
77           let remoteClusterUrl = '';
78           if (
79             this.remoteClusterForm &&
80             this.remoteClusterForm.getValue('remoteClusterUrl') &&
81             this.remoteClusterForm.getValue('remoteClusterUrl').endsWith('/')
82           ) {
83             remoteClusterUrl = this.remoteClusterForm.getValue('remoteClusterUrl').slice(0, -1);
84           } else if (this.remoteClusterForm) {
85             remoteClusterUrl = this.remoteClusterForm.getValue('remoteClusterUrl');
86           }
87           return (
88             this.remoteClusterForm &&
89             this.clusterUrls?.includes(remoteClusterUrl) &&
90             this.clusterUsers?.includes(username)
91           );
92         })
93       ]),
94       password: new FormControl(
95         null,
96         CdValidators.custom('requiredNotEdit', (value: string) => {
97           return this.action !== 'edit' && !value;
98         })
99       ),
100       remoteClusterUrl: new FormControl(null, {
101         validators: [
102           CdValidators.url,
103           CdValidators.custom('hubUrlCheck', (remoteClusterUrl: string) => {
104             return this.action === 'connect' && remoteClusterUrl?.includes(this.hubUrl);
105           }),
106           Validators.required
107         ]
108       }),
109       clusterAlias: new FormControl(null, {
110         validators: [
111           Validators.required,
112           CdValidators.custom('uniqueName', (clusterAlias: string) => {
113             return (
114               (this.action === 'connect' || this.action === 'edit') &&
115               this.clusterAliasNames &&
116               this.clusterAliasNames.indexOf(clusterAlias) !== -1 &&
117               this.cluster?.cluster_alias &&
118               this.cluster.cluster_alias !== clusterAlias
119             );
120           })
121         ]
122       }),
123       ssl: new FormControl(false),
124       ttl: new FormControl(15),
125       ssl_cert: new FormControl('', {
126         validators: [
127           CdValidators.requiredIf({
128             ssl: true
129           })
130         ]
131       })
132     });
133   }
134
135   ngOnDestroy() {
136     this.subs.unsubscribe();
137   }
138
139   handleError(error: any): void {
140     if (error.error.code === 'connection_refused') {
141       this.connectionVerified = false;
142       this.connectionMessage = error.error.detail;
143     } else {
144       this.connectionVerified = false;
145       this.connectionMessage = error.error.detail;
146     }
147     this.remoteClusterForm.setErrors({ cdSubmitButton: true });
148     this.notificationService.show(
149       NotificationType.error,
150       $localize`Connection to the cluster failed`
151     );
152   }
153
154   handleSuccess(message?: string): void {
155     this.notificationService.show(NotificationType.success, message);
156     this.submitAction.emit();
157     this.activeModal.close();
158   }
159
160   convertToHours(value: number): number {
161     return value * 24; // Convert days to hours
162   }
163
164   onSubmit() {
165     const url = this.remoteClusterForm.getValue('remoteClusterUrl');
166     const updatedUrl = url.endsWith('/') ? url.slice(0, -1) : url;
167     const clusterAlias = this.remoteClusterForm.getValue('clusterAlias');
168     const username = this.remoteClusterForm.getValue('username');
169     const password = this.remoteClusterForm.getValue('password');
170     const ssl = this.remoteClusterForm.getValue('ssl');
171     const ttl = this.convertToHours(this.remoteClusterForm.getValue('ttl'));
172     const ssl_certificate = this.remoteClusterForm.getValue('ssl_cert')?.trim();
173
174     const commonSubscribtion = {
175       error: (error: any) => this.handleError(error),
176       next: (response: any) => {
177         if (response === true) {
178           this.handleSuccess($localize`Cluster connected successfully`);
179         }
180       }
181     };
182
183     switch (this.action) {
184       case 'edit':
185         this.subs.add(
186           this.multiClusterService
187             .editCluster(
188               this.cluster.name,
189               url,
190               clusterAlias,
191               this.cluster.user,
192               ssl,
193               ssl_certificate
194             )
195             .subscribe({
196               ...commonSubscribtion,
197               complete: () => this.handleSuccess($localize`Cluster updated successfully`)
198             })
199         );
200         break;
201       case 'reconnect':
202         this.subs.add(
203           this.multiClusterService
204             .reConnectCluster(updatedUrl, username, password, ssl, ssl_certificate, ttl)
205             .subscribe(commonSubscribtion)
206         );
207         break;
208       case 'connect':
209         this.subs.add(
210           this.multiClusterService
211             .addCluster(
212               updatedUrl,
213               clusterAlias,
214               username,
215               password,
216               window.location.origin,
217               ssl,
218               ssl_certificate,
219               ttl
220             )
221             .subscribe(commonSubscribtion)
222         );
223         break;
224       default:
225         break;
226     }
227   }
228
229   fileUpload(files: FileList, controlName: string) {
230     const file: File = files[0];
231     const reader = new FileReader();
232     reader.addEventListener('load', (event: ProgressEvent<FileReader>) => {
233       const control: AbstractControl = this.remoteClusterForm.get(controlName);
234       control.setValue(event.target.result);
235       control.markAsDirty();
236       control.markAsTouched();
237       control.updateValueAndValidity();
238     });
239     reader.readAsText(file, 'utf8');
240   }
241 }