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';
15 selector: 'cd-multi-cluster-form',
16 templateUrl: './multi-cluster-form.component.html',
17 styleUrls: ['./multi-cluster-form.component.scss']
19 export class MultiClusterFormComponent implements OnInit, OnDestroy {
21 submitAction = new EventEmitter();
22 clusterApiUrlCmd = 'ceph mgr services';
23 remoteClusterForm: CdFormGroup;
24 connectionVerified: boolean;
25 connectionMessage = '';
26 private subs = new Subscription();
28 cluster: MultiCluster;
29 clustersData: MultiCluster[];
30 clusterAliasNames: string[];
31 clusterUrls: string[];
32 clusterUsers: string[];
33 clusterUrlUserMap: Map<string, string>;
37 public activeModal: NgbActiveModal,
38 public actionLabels: ActionLabelsI18n,
39 public notificationService: NotificationService,
40 private multiClusterService: MultiClusterService
43 this.multiClusterService.subscribe((resp: any) => {
44 this.hubUrl = resp['hub_url'];
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);
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);
66 [this.clusterAliasNames, this.clusterUrls, this.clusterUsers] = [
70 ].map((prop) => this.clustersData?.map((cluster) => cluster[prop]));
74 this.remoteClusterForm = new CdFormGroup({
75 username: new FormControl('', [
76 CdValidators.custom('uniqueUrlandUser', (username: string) => {
77 let remoteClusterUrl = '';
79 this.remoteClusterForm &&
80 this.remoteClusterForm.getValue('remoteClusterUrl') &&
81 this.remoteClusterForm.getValue('remoteClusterUrl').endsWith('/')
83 remoteClusterUrl = this.remoteClusterForm.getValue('remoteClusterUrl').slice(0, -1);
84 } else if (this.remoteClusterForm) {
85 remoteClusterUrl = this.remoteClusterForm.getValue('remoteClusterUrl');
88 this.remoteClusterForm &&
89 this.clusterUrls?.includes(remoteClusterUrl) &&
90 this.clusterUsers?.includes(username)
94 password: new FormControl(
96 CdValidators.custom('requiredNotEdit', (value: string) => {
97 return this.action !== 'edit' && !value;
100 remoteClusterUrl: new FormControl(null, {
103 CdValidators.custom('hubUrlCheck', (remoteClusterUrl: string) => {
104 return this.action === 'connect' && remoteClusterUrl?.includes(this.hubUrl);
109 clusterAlias: new FormControl(null, {
112 CdValidators.custom('uniqueName', (clusterAlias: string) => {
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
123 ssl: new FormControl(false),
124 ttl: new FormControl(15),
125 ssl_cert: new FormControl('', {
127 CdValidators.requiredIf({
136 this.subs.unsubscribe();
139 handleError(error: any): void {
140 if (error.error.code === 'connection_refused') {
141 this.connectionVerified = false;
142 this.connectionMessage = error.error.detail;
144 this.connectionVerified = false;
145 this.connectionMessage = error.error.detail;
147 this.remoteClusterForm.setErrors({ cdSubmitButton: true });
148 this.notificationService.show(
149 NotificationType.error,
150 $localize`Connection to the cluster failed`
154 handleSuccess(message?: string): void {
155 this.notificationService.show(NotificationType.success, message);
156 this.submitAction.emit();
157 this.activeModal.close();
160 convertToHours(value: number): number {
161 return value * 24; // Convert days to hours
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();
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`);
183 switch (this.action) {
186 this.multiClusterService
196 ...commonSubscribtion,
197 complete: () => this.handleSuccess($localize`Cluster updated successfully`)
203 this.multiClusterService
204 .reConnectCluster(updatedUrl, username, password, ssl, ssl_certificate, ttl)
205 .subscribe(commonSubscribtion)
210 this.multiClusterService
216 window.location.origin,
221 .subscribe(commonSubscribtion)
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();
239 reader.readAsText(file, 'utf8');