Alerting: for cortex am, load default config from status if theres no user config (#35769)

This commit is contained in:
Domas 2021-06-23 19:32:42 +03:00 committed by GitHub
parent 15171ffa3b
commit d480bbf262
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 11 deletions

View File

@ -7,8 +7,14 @@ import { locationService, setDataSourceSrv } from '@grafana/runtime';
import { act, render } from '@testing-library/react';
import { getAllDataSources } from './utils/config';
import { typeAsJestMock } from 'test/helpers/typeAsJestMock';
import { updateAlertManagerConfig, fetchAlertManagerConfig } from './api/alertmanager';
import { mockDataSource, MockDataSourceSrv, someCloudAlertManagerConfig, someGrafanaAlertManagerConfig } from './mocks';
import { updateAlertManagerConfig, fetchAlertManagerConfig, fetchStatus } from './api/alertmanager';
import {
mockDataSource,
MockDataSourceSrv,
someCloudAlertManagerConfig,
someCloudAlertManagerStatus,
someGrafanaAlertManagerConfig,
} from './mocks';
import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
import { fetchNotifiers } from './api/grafana';
import { grafanaNotifiersMock } from './mocks/grafana-notifiers';
@ -27,6 +33,7 @@ const mocks = {
api: {
fetchConfig: typeAsJestMock(fetchAlertManagerConfig),
fetchStatus: typeAsJestMock(fetchStatus),
updateConfig: typeAsJestMock(updateAlertManagerConfig),
fetchNotifiers: typeAsJestMock(fetchNotifiers),
},
@ -302,4 +309,25 @@ describe('Receivers', () => {
},
});
}, 10000);
it('Loads config from status endpoint if there is no user config', async () => {
// loading an empty config with make it fetch config from status endpoint
mocks.api.fetchConfig.mockResolvedValue({
template_files: {},
alertmanager_config: {},
});
mocks.api.fetchStatus.mockResolvedValue(someCloudAlertManagerStatus);
await renderReceivers('CloudManager');
// check that receiver from the default config is represented
const receiversTable = await ui.receiversTable.find();
const receiverRows = receiversTable.querySelectorAll<HTMLTableRowElement>('tbody tr');
expect(receiverRows[0]).toHaveTextContent('default-email');
// check that both config and status endpoints were called
expect(mocks.api.fetchConfig).toHaveBeenCalledTimes(1);
expect(mocks.api.fetchConfig).toHaveBeenLastCalledWith('CloudManager');
expect(mocks.api.fetchStatus).toHaveBeenCalledTimes(1);
expect(mocks.api.fetchStatus).toHaveBeenLastCalledWith('CloudManager');
});
});

View File

@ -7,6 +7,7 @@ import {
Silence,
SilenceCreatePayload,
Matcher,
AlertmanagerStatus,
} from 'app/plugins/datasource/alertmanager/types';
import { getDatasourceAPIId, GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource';
@ -131,6 +132,18 @@ export async function fetchAlertGroups(alertmanagerSourceName: string): Promise<
return result.data;
}
export async function fetchStatus(alertManagerSourceName: string): Promise<AlertmanagerStatus> {
const result = await getBackendSrv()
.fetch<AlertmanagerStatus>({
url: `/api/alertmanager/${getDatasourceAPIId(alertManagerSourceName)}/api/v2/status`,
showErrorAlert: false,
showSuccessAlert: false,
})
.toPromise();
return result.data;
}
function escapeQuotes(value: string): string {
return value.replace(/"/g, '\\"');
}

View File

@ -3,7 +3,11 @@ import { PromAlertingRuleState, PromRuleType } from 'app/types/unified-alerting-
import { AlertingRule, Alert, RecordingRule, RuleGroup, RuleNamespace } from 'app/types/unified-alerting';
import DatasourceSrv from 'app/features/plugins/datasource_srv';
import { DataSourceSrv, GetDataSourceListFilters } from '@grafana/runtime';
import { AlertManagerCortexConfig, GrafanaManagedReceiverConfig } from 'app/plugins/datasource/alertmanager/types';
import {
AlertManagerCortexConfig,
AlertmanagerStatus,
GrafanaManagedReceiverConfig,
} from 'app/plugins/datasource/alertmanager/types';
let nextDataSourceId = 1;
@ -176,6 +180,37 @@ export const someGrafanaAlertManagerConfig: AlertManagerCortexConfig = {
},
};
export const someCloudAlertManagerStatus: AlertmanagerStatus = {
cluster: {
peers: [],
status: 'ok',
},
uptime: '10 hours',
versionInfo: {
branch: '',
version: '',
goVersion: '',
buildDate: '',
buildUser: '',
revision: '',
},
config: {
route: {
receiver: 'default-email',
},
receivers: [
{
name: 'default-email',
email_configs: [
{
to: 'example@example.com',
},
],
},
],
},
};
export const someCloudAlertManagerConfig: AlertManagerCortexConfig = {
template_files: {
'foo template': 'foo content',

View File

@ -22,6 +22,7 @@ import {
fetchSilences,
createOrUpdateSilence,
updateAlertManagerConfig,
fetchStatus,
} from '../api/alertmanager';
import { fetchRules } from '../api/prometheus';
import {
@ -47,6 +48,7 @@ import {
} from '../utils/rules';
import { addDefaultsToAlertmanagerConfig } from '../utils/alertmanager';
import { backendSrv } from 'app/core/services/backend_srv';
import { isEmpty } from 'lodash';
export const fetchPromRulesAction = createAsyncThunk(
'unifiedalerting/fetchPromRules',
@ -56,7 +58,18 @@ export const fetchPromRulesAction = createAsyncThunk(
export const fetchAlertManagerConfigAction = createAsyncThunk(
'unifiedalerting/fetchAmConfig',
(alertManagerSourceName: string): Promise<AlertManagerCortexConfig> =>
withSerializedError(fetchAlertManagerConfig(alertManagerSourceName))
withSerializedError(
fetchAlertManagerConfig(alertManagerSourceName).then((result) => {
// if user config is empty for cortex alertmanager, try to get config from status endpoint
if (isEmpty(result.alertmanager_config) && alertManagerSourceName !== GRAFANA_RULES_SOURCE_NAME) {
return fetchStatus(alertManagerSourceName).then((status) => ({
alertmanager_config: status.config,
template_files: {},
}));
}
return result;
})
)
);
export const fetchRulerRulesAction = createAsyncThunk(

View File

@ -5,13 +5,6 @@ export type AlertManagerCortexConfig = {
alertmanager_config: AlertmanagerConfig;
};
// NOTE - This type is incomplete! But currently, we don't need more.
export type AlertmanagerStatusPayload = {
config: {
original: string;
};
};
export type TLSConfig = {
ca_file: string;
cert_file: string;
@ -217,3 +210,20 @@ export type AlertmanagerGroup = {
alerts: AlertmanagerAlert[];
id: string;
};
export interface AlertmanagerStatus {
cluster: {
peers: unknown;
status: string;
};
config: AlertmanagerConfig;
uptime: string;
versionInfo: {
branch: string;
buildDate: string;
buildUser: string;
goVersion: string;
revision: string;
version: string;
};
}