grafana/public/app/features/alerting/unified/hooks/useExternalAmSelector.ts
Alex Moreno 45facbba11
Alerting: Remove url based external alertmanagers config (#57918)
* Remove URL-based alertmanagers from endpoint config

* WIP

* Add migration and alertmanagers from admin_configuration

* Empty comment removed

* set BasicAuth true when user is present in url

* Remove Alertmanagers from GET /admin_config payload

* Remove URL-based alertmanager configuration from UI

* Fix new uid generation in external alertmanagers migration

* Fix tests for URL-based external alertmanagers

* Fix API tests

* Add more tests, move migration code to separate file, and remove possible am duplicate urls

* Fix edge cases in migration

* Fix imports

* Remove useless fields and fix created_at/updated_at retrieval

Co-authored-by: George Robinson <george.robinson@grafana.com>
Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com>
2022-11-10 16:34:13 +01:00

76 lines
2.7 KiB
TypeScript

import { countBy, keyBy } from 'lodash';
import { DataSourceInstanceSettings, DataSourceJsonData, DataSourceSettings } from '@grafana/data';
import { AlertManagerDataSourceJsonData } from 'app/plugins/datasource/alertmanager/types';
import { useSelector } from 'app/types';
import { alertmanagerApi } from '../api/alertmanagerApi';
import { getAlertManagerDataSources } from '../utils/datasource';
export interface ExternalDataSourceAM {
dataSource: DataSourceInstanceSettings<AlertManagerDataSourceJsonData>;
url?: string;
status: 'active' | 'pending' | 'dropped';
statusInconclusive?: boolean;
}
export function useExternalDataSourceAlertmanagers(): ExternalDataSourceAM[] {
const { useGetExternalAlertmanagersQuery } = alertmanagerApi;
const { currentData: discoveredAlertmanagers } = useGetExternalAlertmanagersQuery();
const externalDsAlertManagers = getAlertManagerDataSources().filter((ds) => ds.jsonData.handleGrafanaManagedAlerts);
const alertmanagerDatasources = useSelector((state) =>
keyBy(
state.dataSources.dataSources.filter((ds) => ds.type === 'alertmanager'),
(ds) => ds.uid
)
);
const droppedAMUrls = countBy(discoveredAlertmanagers?.droppedAlertManagers, (x) => x.url);
const activeAMUrls = countBy(discoveredAlertmanagers?.activeAlertManagers, (x) => x.url);
return externalDsAlertManagers.map<ExternalDataSourceAM>((dsAm) => {
const dsSettings = alertmanagerDatasources[dsAm.uid];
if (!dsSettings) {
return {
dataSource: dsAm,
status: 'pending',
};
}
const amUrl = getDataSourceUrlWithProtocol(dsSettings);
const amStatusUrl = `${amUrl}/api/v2/alerts`;
const matchingDroppedUrls = droppedAMUrls[amStatusUrl] ?? 0;
const matchingActiveUrls = activeAMUrls[amStatusUrl] ?? 0;
const isDropped = matchingDroppedUrls > 0;
const isActive = matchingActiveUrls > 0;
// Multiple Alertmanagers of the same URL may exist (e.g. with different credentials)
// Alertmanager response only contains URLs, so in case of duplication, we are not able
// to distinguish which is which, resulting in an inconclusive status.
const isStatusInconclusive = matchingDroppedUrls + matchingActiveUrls > 1;
const status = isDropped ? 'dropped' : isActive ? 'active' : 'pending';
return {
dataSource: dsAm,
url: dsSettings.url,
status,
statusInconclusive: isStatusInconclusive,
};
});
}
function getDataSourceUrlWithProtocol<T extends DataSourceJsonData>(dsSettings: DataSourceSettings<T>) {
const hasProtocol = new RegExp('^[^:]*://').test(dsSettings.url);
if (!hasProtocol) {
return `http://${dsSettings.url}`; // Grafana append http protocol if there is no any
}
return dsSettings.url;
}