]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-list/silence-list.component.ts
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / prometheus / silence-list / silence-list.component.ts
CommitLineData
f67539c2 1import { Component, Inject } from '@angular/core';
494da23a 2
f67539c2
TL
3import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
4import { SortDirection, SortPropDir } from '@swimlane/ngx-datatable';
494da23a
TL
5import { Observable, Subscriber } from 'rxjs';
6
1e59de90 7import { PrometheusListHelper } from '~/app/shared/helpers/prometheus-list-helper';
39ae355f 8import { SilenceFormComponent } from '~/app/ceph/cluster/prometheus/silence-form/silence-form.component';
f67539c2
TL
9import { PrometheusService } from '~/app/shared/api/prometheus.service';
10import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
11import { ActionLabelsI18n, SucceededActionLabelsI18n } from '~/app/shared/constants/app.constants';
12import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
13import { Icons } from '~/app/shared/enum/icons.enum';
14import { NotificationType } from '~/app/shared/enum/notification-type.enum';
15import { AlertmanagerSilence } from '~/app/shared/models/alertmanager-silence';
16import { CdTableAction } from '~/app/shared/models/cd-table-action';
17import { CdTableColumn } from '~/app/shared/models/cd-table-column';
18import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
19import { Permission } from '~/app/shared/models/permissions';
39ae355f 20import { PrometheusRule } from '~/app/shared/models/prometheus-alerts';
f67539c2
TL
21import { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe';
22import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
23import { ModalService } from '~/app/shared/services/modal.service';
24import { NotificationService } from '~/app/shared/services/notification.service';
39ae355f 25import { PrometheusSilenceMatcherService } from '~/app/shared/services/prometheus-silence-matcher.service';
f67539c2 26import { URLBuilderService } from '~/app/shared/services/url-builder.service';
494da23a 27
f67539c2 28const BASE_URL = 'monitoring/silences';
494da23a
TL
29
30@Component({
39ae355f
TL
31 providers: [
32 { provide: URLBuilderService, useValue: new URLBuilderService(BASE_URL) },
33 SilenceFormComponent
34 ],
494da23a
TL
35 selector: 'cd-silences-list',
36 templateUrl: './silence-list.component.html',
37 styleUrls: ['./silence-list.component.scss']
38})
f67539c2 39export class SilenceListComponent extends PrometheusListHelper {
494da23a
TL
40 silences: AlertmanagerSilence[] = [];
41 columns: CdTableColumn[];
42 tableActions: CdTableAction[];
43 permission: Permission;
44 selection = new CdTableSelection();
f67539c2 45 modalRef: NgbModalRef;
494da23a 46 customCss = {
9f95a23c
TL
47 'badge badge-danger': 'active',
48 'badge badge-warning': 'pending',
49 'badge badge-default': 'expired'
494da23a
TL
50 };
51 sorts: SortPropDir[] = [{ prop: 'endsAt', dir: SortDirection.desc }];
39ae355f
TL
52 rules: PrometheusRule[];
53 visited: boolean;
494da23a
TL
54
55 constructor(
56 private authStorageService: AuthStorageService,
494da23a 57 private cdDatePipe: CdDatePipe,
f67539c2 58 private modalService: ModalService,
494da23a
TL
59 private notificationService: NotificationService,
60 private urlBuilder: URLBuilderService,
61 private actionLabels: ActionLabelsI18n,
f67539c2 62 private succeededLabels: SucceededActionLabelsI18n,
39ae355f
TL
63 private silenceFormComponent: SilenceFormComponent,
64 private silenceMatcher: PrometheusSilenceMatcherService,
f67539c2 65 @Inject(PrometheusService) prometheusService: PrometheusService
494da23a 66 ) {
f67539c2 67 super(prometheusService);
494da23a 68 this.permission = this.authStorageService.getPermissions().prometheus;
494da23a 69 const selectionExpired = (selection: CdTableSelection) =>
9f95a23c 70 selection.first() && selection.first().status && selection.first().status.state === 'expired';
494da23a
TL
71 this.tableActions = [
72 {
73 permission: 'create',
74 icon: Icons.add,
75 routerLink: () => this.urlBuilder.getCreate(),
76 canBePrimary: (selection: CdTableSelection) => !selection.hasSingleSelection,
77 name: this.actionLabels.CREATE
78 },
79 {
80 permission: 'create',
81 canBePrimary: (selection: CdTableSelection) =>
82 selection.hasSingleSelection && selectionExpired(selection),
83 disable: (selection: CdTableSelection) =>
84 !selection.hasSingleSelection ||
85 selection.first().cdExecuting ||
86 (selection.first().cdExecuting && selectionExpired(selection)) ||
87 !selectionExpired(selection),
88 icon: Icons.copy,
89 routerLink: () => this.urlBuilder.getRecreate(this.selection.first().id),
90 name: this.actionLabels.RECREATE
91 },
92 {
93 permission: 'update',
94 icon: Icons.edit,
95 canBePrimary: (selection: CdTableSelection) =>
96 selection.hasSingleSelection && !selectionExpired(selection),
97 disable: (selection: CdTableSelection) =>
98 !selection.hasSingleSelection ||
99 selection.first().cdExecuting ||
100 (selection.first().cdExecuting && !selectionExpired(selection)) ||
101 selectionExpired(selection),
102 routerLink: () => this.urlBuilder.getEdit(this.selection.first().id),
103 name: this.actionLabels.EDIT
104 },
105 {
106 permission: 'delete',
107 icon: Icons.trash,
108 canBePrimary: (selection: CdTableSelection) =>
109 selection.hasSingleSelection && !selectionExpired(selection),
110 disable: (selection: CdTableSelection) =>
111 !selection.hasSingleSelection ||
112 selection.first().cdExecuting ||
113 selectionExpired(selection),
114 click: () => this.expireSilence(),
115 name: this.actionLabels.EXPIRE
116 }
117 ];
118 this.columns = [
119 {
f67539c2 120 name: $localize`ID`,
494da23a
TL
121 prop: 'id',
122 flexGrow: 3
123 },
39ae355f
TL
124 {
125 name: $localize`Alerts Silenced`,
126 prop: 'silencedAlerts',
127 flexGrow: 3,
128 cellTransformation: CellTemplate.badge
129 },
494da23a 130 {
f67539c2 131 name: $localize`Created by`,
494da23a
TL
132 prop: 'createdBy',
133 flexGrow: 2
134 },
135 {
f67539c2 136 name: $localize`Started`,
494da23a
TL
137 prop: 'startsAt',
138 pipe: this.cdDatePipe
139 },
140 {
f67539c2 141 name: $localize`Updated`,
494da23a
TL
142 prop: 'updatedAt',
143 pipe: this.cdDatePipe
144 },
145 {
f67539c2 146 name: $localize`Ends`,
494da23a
TL
147 prop: 'endsAt',
148 pipe: this.cdDatePipe
149 },
150 {
f67539c2 151 name: $localize`Status`,
494da23a
TL
152 prop: 'status.state',
153 cellTransformation: CellTemplate.classAdding
154 }
155 ];
156 }
157
158 refresh() {
159 this.prometheusService.ifAlertmanagerConfigured(() => {
160 this.prometheusService.getSilences().subscribe(
161 (silences) => {
162 this.silences = silences;
39ae355f
TL
163 const activeSilences = silences.filter(
164 (silence: AlertmanagerSilence) => silence.status.state !== 'expired'
165 );
166 this.getAlerts(activeSilences);
494da23a
TL
167 },
168 () => {
169 this.prometheusService.disableAlertmanagerConfig();
170 }
171 );
172 });
173 }
174
175 updateSelection(selection: CdTableSelection) {
176 this.selection = selection;
177 }
178
39ae355f
TL
179 getAlerts(silences: any) {
180 const rules = this.silenceFormComponent.getRules();
181 silences.forEach((silence: any) => {
182 silence.matchers.forEach((matcher: any) => {
183 this.rules = this.silenceMatcher.getMatchedRules(matcher, rules);
184 const alertNames: string[] = [];
185 for (const rule of this.rules) {
186 alertNames.push(rule.name);
187 }
188 silence.silencedAlerts = alertNames;
189 });
190 });
191 }
192
494da23a
TL
193 expireSilence() {
194 const id = this.selection.first().id;
f67539c2 195 const i18nSilence = $localize`Silence`;
494da23a
TL
196 const applicationName = 'Prometheus';
197 this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
f67539c2
TL
198 itemDescription: i18nSilence,
199 itemNames: [id],
200 actionDescription: this.actionLabels.EXPIRE,
201 submitActionObservable: () =>
202 new Observable((observer: Subscriber<any>) => {
203 this.prometheusService.expireSilence(id).subscribe(
204 () => {
205 this.notificationService.show(
206 NotificationType.success,
207 `${this.succeededLabels.EXPIRED} ${i18nSilence} ${id}`,
208 undefined,
209 undefined,
210 applicationName
211 );
212 },
213 (resp) => {
214 resp['application'] = applicationName;
215 observer.error(resp);
216 },
217 () => {
218 observer.complete();
219 this.refresh();
220 }
221 );
222 })
494da23a
TL
223 });
224 }
225}