]> git.apps.os.sepia.ceph.com Git - ceph.git/blob
da5e08dfebea4fc8af3a5c2cc862b8bc3ce38bbf
[ceph.git] /
1 import { Component, TemplateRef, ViewChild } from '@angular/core';
2 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
3 import { MultiClusterService } from '~/app/shared/api/multi-cluster.service';
4 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
5 import { Icons } from '~/app/shared/enum/icons.enum';
6 import { CdTableAction } from '~/app/shared/models/cd-table-action';
7 import { CdTableColumn } from '~/app/shared/models/cd-table-column';
8 import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
9 import { ModalService } from '~/app/shared/services/modal.service';
10 import { MultiClusterFormComponent } from '../multi-cluster-form/multi-cluster-form.component';
11 import { TableComponent } from '~/app/shared/datatable/table/table.component';
12 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
13 import { Permissions } from '~/app/shared/models/permissions';
14 import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
15 import { NotificationService } from '~/app/shared/services/notification.service';
16 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
17 import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
18 import { MultiCluster } from '~/app/shared/models/multi-cluster';
19 import { Router } from '@angular/router';
20 import { CookiesService } from '~/app/shared/services/cookie.service';
21
22 @Component({
23   selector: 'cd-multi-cluster-list',
24   templateUrl: './multi-cluster-list.component.html',
25   styleUrls: ['./multi-cluster-list.component.scss']
26 })
27 export class MultiClusterListComponent {
28   @ViewChild(TableComponent)
29   table: TableComponent;
30   @ViewChild('urlTpl', { static: true })
31   public urlTpl: TemplateRef<any>;
32
33   permissions: Permissions;
34   tableActions: CdTableAction[];
35   clusterTokenStatus: object = {};
36   columns: Array<CdTableColumn> = [];
37   data: any;
38   selection = new CdTableSelection();
39   bsModalRef: NgbModalRef;
40   clustersTokenMap: Map<string, string> = new Map<string, string>();
41   newData: any;
42   modalRef: NgbModalRef;
43   hubUrl: string;
44   currentUrl: string;
45
46   constructor(
47     private multiClusterService: MultiClusterService,
48     private router: Router,
49     public actionLabels: ActionLabelsI18n,
50     private notificationService: NotificationService,
51     private authStorageService: AuthStorageService,
52     private modalService: ModalService,
53     private cookieService: CookiesService
54   ) {
55     this.tableActions = [
56       {
57         permission: 'create',
58         icon: Icons.add,
59         name: this.actionLabels.CONNECT,
60         disable: (selection: CdTableSelection) => this.getDisable('connect', selection),
61         click: () => this.openRemoteClusterInfoModal('connect')
62       },
63       {
64         permission: 'update',
65         icon: Icons.edit,
66         name: this.actionLabels.EDIT,
67         disable: (selection: CdTableSelection) => this.getDisable('edit', selection),
68         click: () => this.openRemoteClusterInfoModal('edit')
69       },
70       {
71         permission: 'update',
72         icon: Icons.refresh,
73         name: this.actionLabels.RECONNECT,
74         disable: (selection: CdTableSelection) => this.getDisable('reconnect', selection),
75         click: () => this.openRemoteClusterInfoModal('reconnect')
76       },
77       {
78         permission: 'delete',
79         icon: Icons.destroy,
80         name: this.actionLabels.DISCONNECT,
81         disable: (selection: CdTableSelection) => this.getDisable('disconnect', selection),
82         click: () => this.openDeleteClusterModal()
83       }
84     ];
85     this.permissions = this.authStorageService.getPermissions();
86   }
87
88   ngOnInit(): void {
89     this.multiClusterService.subscribe((resp: object) => {
90       if (resp && resp['config']) {
91         this.hubUrl = resp['hub_url'];
92         this.currentUrl = resp['current_url'];
93         const clusterDetailsArray = Object.values(resp['config']).flat();
94         this.data = clusterDetailsArray;
95         this.checkClusterConnectionStatus();
96       }
97     });
98
99     this.columns = [
100       {
101         prop: 'cluster_alias',
102         name: $localize`Alias`,
103         flexGrow: 2
104       },
105       {
106         prop: 'cluster_connection_status',
107         name: $localize`Connection`,
108         flexGrow: 2,
109         cellTransformation: CellTemplate.badge,
110         customTemplateConfig: {
111           map: {
112             1: { value: 'DISCONNECTED', class: 'badge-danger' },
113             0: { value: 'CONNECTED', class: 'badge-success' },
114             2: { value: 'CHECKING..', class: 'badge-info' }
115           }
116         }
117       },
118       {
119         prop: 'name',
120         name: $localize`FSID`,
121         flexGrow: 2
122       },
123       {
124         prop: 'url',
125         name: $localize`URL`,
126         flexGrow: 2,
127         cellTemplate: this.urlTpl
128       },
129       {
130         prop: 'user',
131         name: $localize`User`,
132         flexGrow: 2
133       }
134     ];
135
136     this.multiClusterService.subscribeClusterTokenStatus((resp: object) => {
137       this.clusterTokenStatus = resp;
138       this.checkClusterConnectionStatus();
139     });
140   }
141
142   checkClusterConnectionStatus() {
143     if (this.clusterTokenStatus && this.data) {
144       this.data.forEach((cluster: MultiCluster) => {
145         const clusterStatus = this.clusterTokenStatus[cluster.name.trim()];
146
147         if (clusterStatus !== undefined) {
148           cluster.cluster_connection_status = clusterStatus.status;
149         } else {
150           cluster.cluster_connection_status = 2;
151         }
152
153         if (cluster.cluster_alias === 'local-cluster') {
154           cluster.cluster_connection_status = 0;
155         }
156       });
157     }
158   }
159
160   openRemoteClusterInfoModal(action: string) {
161     const initialState = {
162       clustersData: this.data,
163       action: action,
164       cluster: this.selection.first()
165     };
166     this.bsModalRef = this.modalService.show(MultiClusterFormComponent, initialState, {
167       size: 'xl'
168     });
169     this.bsModalRef.componentInstance.submitAction.subscribe(() => {
170       const currentRoute = this.router.url.split('?')[0];
171       this.multiClusterService.refreshMultiCluster(currentRoute);
172       this.checkClusterConnectionStatus();
173       this.multiClusterService.isClusterAdded(true);
174     });
175   }
176
177   updateSelection(selection: CdTableSelection) {
178     this.selection = selection;
179   }
180
181   openDeleteClusterModal() {
182     const cluster = this.selection.first();
183     this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
184       infoMessage: $localize`Please note that the data for the disconnected cluster will be visible for a duration of ~ 5 minutes. After this period, it will be automatically removed.`,
185       actionDescription: $localize`Disconnect`,
186       itemDescription: $localize`Cluster`,
187       itemNames: [cluster['cluster_alias'] + ' - ' + cluster['user']],
188       submitAction: () =>
189         this.multiClusterService.deleteCluster(cluster['name'], cluster['user']).subscribe(() => {
190           this.cookieService.deleteToken(`${cluster['name']}-${cluster['user']}`);
191           this.multiClusterService.showPrometheusDelayMessage(true);
192           this.modalRef.close();
193           this.notificationService.show(
194             NotificationType.success,
195             $localize`Disconnected cluster '${cluster['cluster_alias']}'`
196           );
197           const currentRoute = this.router.url.split('?')[0];
198           this.multiClusterService.refreshMultiCluster(currentRoute);
199         })
200     });
201   }
202
203   getDisable(action: string, selection: CdTableSelection): string | boolean {
204     if (this.hubUrl !== this.currentUrl) {
205       return $localize`Please switch to the local-cluster to ${action} a remote cluster`;
206     }
207     if (!selection.hasSelection && action !== 'connect') {
208       return $localize`Please select one or more clusters to ${action}`;
209     }
210     if (selection.hasSingleSelection) {
211       const cluster = selection.first();
212       if (cluster['cluster_alias'] === 'local-cluster' && action !== 'connect') {
213         return $localize`Cannot ${action} local cluster`;
214       }
215     }
216     return false;
217   }
218 }