mirror of
https://github.com/grafana/grafana.git
synced 2025-01-15 11:12:50 -06:00
Alerting: Use alerting API server for contact points list (#91073)
This commit is contained in:
parent
a223c46506
commit
338b318bf4
@ -42,7 +42,12 @@ const ContactPointsTab = () => {
|
|||||||
const { selectedAlertmanager } = useAlertmanager();
|
const { selectedAlertmanager } = useAlertmanager();
|
||||||
const [queryParams] = useURLSearchParams();
|
const [queryParams] = useURLSearchParams();
|
||||||
|
|
||||||
const { isLoading, error, contactPoints } = useContactPointsWithStatus();
|
const { isLoading, error, contactPoints } = useContactPointsWithStatus({
|
||||||
|
alertmanager: selectedAlertmanager!,
|
||||||
|
fetchPolicies: true,
|
||||||
|
fetchStatuses: true,
|
||||||
|
});
|
||||||
|
|
||||||
const { deleteTrigger, updateAlertmanagerState } = useDeleteContactPoint(selectedAlertmanager!);
|
const { deleteTrigger, updateAlertmanagerState } = useDeleteContactPoint(selectedAlertmanager!);
|
||||||
const [addContactPointSupported, addContactPointAllowed] = useAlertmanagerAbility(
|
const [addContactPointSupported, addContactPointAllowed] = useAlertmanagerAbility(
|
||||||
AlertmanagerAction.CreateContactPoint
|
AlertmanagerAction.CreateContactPoint
|
||||||
@ -160,7 +165,9 @@ const ContactPointsPageContents = () => {
|
|||||||
const { selectedAlertmanager } = useAlertmanager();
|
const { selectedAlertmanager } = useAlertmanager();
|
||||||
const [activeTab, setActiveTab] = useTabQueryParam();
|
const [activeTab, setActiveTab] = useTabQueryParam();
|
||||||
|
|
||||||
const { contactPoints } = useContactPointsWithStatus();
|
const { contactPoints } = useContactPointsWithStatus({
|
||||||
|
alertmanager: selectedAlertmanager!,
|
||||||
|
});
|
||||||
|
|
||||||
const showingContactPoints = activeTab === ActiveTab.ContactPoints;
|
const showingContactPoints = activeTab === ActiveTab.ContactPoints;
|
||||||
const showNotificationTemplates = activeTab === ActiveTab.NotificationTemplates;
|
const showNotificationTemplates = activeTab === ActiveTab.NotificationTemplates;
|
||||||
|
@ -2,66 +2,79 @@ import { renderHook, waitFor } from '@testing-library/react';
|
|||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { getWrapper } from 'test/test-utils';
|
import { getWrapper } from 'test/test-utils';
|
||||||
|
|
||||||
|
import { config } from '@grafana/runtime';
|
||||||
import { disablePlugin } from 'app/features/alerting/unified/mocks/server/configure';
|
import { disablePlugin } from 'app/features/alerting/unified/mocks/server/configure';
|
||||||
import { setOnCallIntegrations } from 'app/features/alerting/unified/mocks/server/handlers/plugins/configure-plugins';
|
import { setOnCallIntegrations } from 'app/features/alerting/unified/mocks/server/handlers/plugins/configure-plugins';
|
||||||
import { SupportedPlugin } from 'app/features/alerting/unified/types/pluginBridges';
|
import { SupportedPlugin } from 'app/features/alerting/unified/types/pluginBridges';
|
||||||
|
import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource';
|
||||||
import { AccessControlAction } from 'app/types';
|
import { AccessControlAction } from 'app/types';
|
||||||
|
|
||||||
import { setupMswServer } from '../../mockApi';
|
import { setupMswServer } from '../../mockApi';
|
||||||
import { grantUserPermissions } from '../../mocks';
|
import { grantUserPermissions } from '../../mocks';
|
||||||
import { AlertmanagerProvider } from '../../state/AlertmanagerContext';
|
|
||||||
|
|
||||||
import { useContactPointsWithStatus } from './useContactPoints';
|
import { useContactPointsWithStatus } from './useContactPoints';
|
||||||
|
|
||||||
const wrapper = ({ children }: { children: ReactNode }) => {
|
const wrapper = ({ children }: { children: ReactNode }) => {
|
||||||
const ProviderWrapper = getWrapper({ renderWithRouter: true });
|
const ProviderWrapper = getWrapper({ renderWithRouter: true });
|
||||||
return (
|
return <ProviderWrapper>{children}</ProviderWrapper>;
|
||||||
<ProviderWrapper>
|
|
||||||
<AlertmanagerProvider accessType="notification" alertmanagerSourceName="grafana">
|
|
||||||
{children}
|
|
||||||
</AlertmanagerProvider>
|
|
||||||
</ProviderWrapper>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
setupMswServer();
|
setupMswServer();
|
||||||
|
|
||||||
|
const getHookResponse = async (featureToggleEnabled: boolean) => {
|
||||||
|
config.featureToggles.alertingApiServer = featureToggleEnabled;
|
||||||
|
const { result } = renderHook(
|
||||||
|
() =>
|
||||||
|
useContactPointsWithStatus({
|
||||||
|
alertmanager: GRAFANA_RULES_SOURCE_NAME,
|
||||||
|
fetchPolicies: true,
|
||||||
|
fetchStatuses: true,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
wrapper,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(result.current.isLoading).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only return some properties, as we don't want to compare all
|
||||||
|
// RTK query properties in snapshots/comparison between k8s and non-k8s implementations
|
||||||
|
// (would include properties like requestId, fulfilled, etc.)
|
||||||
|
const { contactPoints, error, isLoading } = result.current;
|
||||||
|
|
||||||
|
return { contactPoints, error, isLoading };
|
||||||
|
};
|
||||||
|
|
||||||
describe('useContactPoints', () => {
|
describe('useContactPoints', () => {
|
||||||
beforeAll(() => {
|
beforeEach(() => {
|
||||||
grantUserPermissions([AccessControlAction.AlertingNotificationsRead]);
|
grantUserPermissions([AccessControlAction.AlertingNotificationsRead]);
|
||||||
|
setOnCallIntegrations([
|
||||||
|
{
|
||||||
|
display_name: 'grafana-integration',
|
||||||
|
value: 'ABC123',
|
||||||
|
integration_url: 'https://oncall-endpoint.example.com',
|
||||||
|
},
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return contact points with status', async () => {
|
it('should return contact points with status', async () => {
|
||||||
disablePlugin(SupportedPlugin.OnCall);
|
disablePlugin(SupportedPlugin.OnCall);
|
||||||
|
const snapshot = await getHookResponse(false);
|
||||||
|
expect(snapshot).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
const { result } = renderHook(() => useContactPointsWithStatus(), {
|
it('returns matching responses with and without alertingApiServer', async () => {
|
||||||
wrapper,
|
const snapshotAmConfig = await getHookResponse(false);
|
||||||
});
|
const snapshotAlertingApiServer = await getHookResponse(true);
|
||||||
|
expect(snapshotAmConfig).toEqual(snapshotAlertingApiServer);
|
||||||
await waitFor(() => {
|
|
||||||
expect(result.current.isLoading).toBe(false);
|
|
||||||
});
|
|
||||||
expect(result.current).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when having oncall plugin installed and no alert manager config data', () => {
|
describe('when having oncall plugin installed and no alert manager config data', () => {
|
||||||
it('should return contact points with oncall metadata', async () => {
|
it('should return contact points with oncall metadata', async () => {
|
||||||
setOnCallIntegrations([
|
const snapshot = await getHookResponse(false);
|
||||||
{
|
expect(snapshot).toMatchSnapshot();
|
||||||
display_name: 'grafana-integration',
|
|
||||||
value: 'ABC123',
|
|
||||||
integration_url: 'https://oncall-endpoint.example.com',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const { result } = renderHook(() => useContactPointsWithStatus(), {
|
|
||||||
wrapper,
|
|
||||||
});
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(result.current.isLoading).toBe(false);
|
|
||||||
});
|
|
||||||
expect(result.current).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
ComGithubGrafanaGrafanaPkgApisAlertingNotificationsV0Alpha1Receiver,
|
ComGithubGrafanaGrafanaPkgApisAlertingNotificationsV0Alpha1Receiver,
|
||||||
generatedReceiversApi,
|
generatedReceiversApi,
|
||||||
} from 'app/features/alerting/unified/openapi/receiversApi.gen';
|
} from 'app/features/alerting/unified/openapi/receiversApi.gen';
|
||||||
|
import { BaseAlertmanagerArgs, Skippable } from 'app/features/alerting/unified/types/hooks';
|
||||||
import { cloudNotifierTypes } from 'app/features/alerting/unified/utils/cloud-alertmanager-notifier-types';
|
import { cloudNotifierTypes } from 'app/features/alerting/unified/utils/cloud-alertmanager-notifier-types';
|
||||||
import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource';
|
import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource';
|
||||||
import { getNamespace, shouldUseK8sApi } from 'app/features/alerting/unified/utils/k8s/utils';
|
import { getNamespace, shouldUseK8sApi } from 'app/features/alerting/unified/utils/k8s/utils';
|
||||||
@ -18,7 +19,6 @@ import { getNamespace, shouldUseK8sApi } from 'app/features/alerting/unified/uti
|
|||||||
import { alertmanagerApi } from '../../api/alertmanagerApi';
|
import { alertmanagerApi } from '../../api/alertmanagerApi';
|
||||||
import { onCallApi } from '../../api/onCallApi';
|
import { onCallApi } from '../../api/onCallApi';
|
||||||
import { usePluginBridge } from '../../hooks/usePluginBridge';
|
import { usePluginBridge } from '../../hooks/usePluginBridge';
|
||||||
import { useAlertmanager } from '../../state/AlertmanagerContext';
|
|
||||||
import { SupportedPlugin } from '../../types/pluginBridges';
|
import { SupportedPlugin } from '../../types/pluginBridges';
|
||||||
|
|
||||||
import { enhanceContactPointsWithMetadata } from './utils';
|
import { enhanceContactPointsWithMetadata } from './utils';
|
||||||
@ -44,12 +44,17 @@ const {
|
|||||||
const { useGrafanaOnCallIntegrationsQuery } = onCallApi;
|
const { useGrafanaOnCallIntegrationsQuery } = onCallApi;
|
||||||
const { useListNamespacedReceiverQuery } = generatedReceiversApi;
|
const { useListNamespacedReceiverQuery } = generatedReceiversApi;
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
refetchOnFocus: true,
|
||||||
|
refetchOnReconnect: true,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if OnCall is installed, and fetch the list of integrations if so.
|
* Check if OnCall is installed, and fetch the list of integrations if so.
|
||||||
*
|
*
|
||||||
* Otherwise, returns no data
|
* Otherwise, returns no data
|
||||||
*/
|
*/
|
||||||
const useOnCallIntegrations = ({ skip }: { skip?: boolean } = {}) => {
|
const useOnCallIntegrations = ({ skip }: Skippable = {}) => {
|
||||||
const { installed, loading } = usePluginBridge(SupportedPlugin.OnCall);
|
const { installed, loading } = usePluginBridge(SupportedPlugin.OnCall);
|
||||||
const oncallIntegrationsResponse = useGrafanaOnCallIntegrationsQuery(undefined, { skip: skip || !installed });
|
const oncallIntegrationsResponse = useGrafanaOnCallIntegrationsQuery(undefined, { skip: skip || !installed });
|
||||||
|
|
||||||
@ -84,24 +89,53 @@ const useK8sContactPoints = (...[hookParams, queryOptions]: Parameters<typeof us
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const useGetGrafanaContactPoints = () => {
|
/**
|
||||||
|
* Fetch contact points for Grafana Alertmanager, either from the k8s API,
|
||||||
|
* or the `/notifications/receivers` endpoint
|
||||||
|
*/
|
||||||
|
const useFetchGrafanaContactPoints = ({ skip }: Skippable = {}) => {
|
||||||
const namespace = getNamespace();
|
const namespace = getNamespace();
|
||||||
const useK8sApi = shouldUseK8sApi(GRAFANA_RULES_SOURCE_NAME);
|
const useK8sApi = shouldUseK8sApi(GRAFANA_RULES_SOURCE_NAME);
|
||||||
const grafanaResponse = useGetContactPointsListQuery(undefined, { skip: useK8sApi });
|
|
||||||
const k8sResponse = useK8sContactPoints({ namespace }, { skip: !useK8sApi });
|
const grafanaResponse = useGetContactPointsListQuery(undefined, { skip: skip || useK8sApi });
|
||||||
|
const k8sResponse = useK8sContactPoints({ namespace }, { skip: skip || !useK8sApi });
|
||||||
|
|
||||||
return useK8sApi ? k8sResponse : grafanaResponse;
|
return useK8sApi ? k8sResponse : grafanaResponse;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type GrafanaFetchOptions = {
|
||||||
|
/**
|
||||||
|
* Should we fetch and include status information about each contact point?
|
||||||
|
*/
|
||||||
|
fetchStatuses?: boolean;
|
||||||
|
/**
|
||||||
|
* Should we fetch and include the number of notification policies that reference each contact point?
|
||||||
|
*/
|
||||||
|
fetchPolicies?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch contact points from separate endpoint (i.e. not the Alertmanager config) and combine with
|
* Fetch contact points from separate endpoint (i.e. not the Alertmanager config) and combine with
|
||||||
* OnCall integrations and any additional metadata from list of notifiers
|
* OnCall integrations and any additional metadata from list of notifiers
|
||||||
* (e.g. hydrate with additional names/descriptions)
|
* (e.g. hydrate with additional names/descriptions)
|
||||||
*/
|
*/
|
||||||
export const useGetContactPoints = () => {
|
export const useGrafanaContactPoints = ({
|
||||||
const onCallResponse = useOnCallIntegrations();
|
fetchStatuses,
|
||||||
const alertNotifiers = useGrafanaNotifiersQuery();
|
fetchPolicies,
|
||||||
const contactPointsListResponse = useGetGrafanaContactPoints();
|
skip,
|
||||||
|
}: GrafanaFetchOptions & Skippable = {}) => {
|
||||||
|
const potentiallySkip = { skip };
|
||||||
|
const onCallResponse = useOnCallIntegrations(potentiallySkip);
|
||||||
|
const alertNotifiers = useGrafanaNotifiersQuery(undefined, potentiallySkip);
|
||||||
|
const contactPointsListResponse = useFetchGrafanaContactPoints(potentiallySkip);
|
||||||
|
const contactPointsStatusResponse = useGetContactPointsStatusQuery(undefined, {
|
||||||
|
...defaultOptions,
|
||||||
|
pollingInterval: RECEIVER_STATUS_POLLING_INTERVAL,
|
||||||
|
skip: skip || !fetchStatuses,
|
||||||
|
});
|
||||||
|
const alertmanagerConfigResponse = useGetAlertmanagerConfigurationQuery(GRAFANA_RULES_SOURCE_NAME, {
|
||||||
|
skip: skip || !fetchPolicies,
|
||||||
|
});
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const isLoading = onCallResponse.isLoading || alertNotifiers.isLoading || contactPointsListResponse.isLoading;
|
const isLoading = onCallResponse.isLoading || alertNotifiers.isLoading || contactPointsListResponse.isLoading;
|
||||||
@ -118,83 +152,55 @@ export const useGetContactPoints = () => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const enhanced = enhanceContactPointsWithMetadata(
|
const enhanced = enhanceContactPointsWithMetadata({
|
||||||
[],
|
status: contactPointsStatusResponse.data,
|
||||||
alertNotifiers.data,
|
notifiers: alertNotifiers.data,
|
||||||
onCallResponse?.data,
|
onCallIntegrations: onCallResponse?.data,
|
||||||
contactPointsListResponse.data,
|
contactPoints: contactPointsListResponse.data,
|
||||||
undefined
|
alertmanagerConfiguration: alertmanagerConfigResponse.data,
|
||||||
);
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...contactPointsListResponse,
|
...contactPointsListResponse,
|
||||||
contactPoints: enhanced,
|
contactPoints: enhanced,
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
alertNotifiers.data,
|
alertNotifiers,
|
||||||
alertNotifiers.isLoading,
|
alertmanagerConfigResponse,
|
||||||
contactPointsListResponse,
|
contactPointsListResponse,
|
||||||
onCallResponse?.data,
|
contactPointsStatusResponse,
|
||||||
onCallResponse.isLoading,
|
onCallResponse,
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useContactPointsWithStatus() {
|
export function useContactPointsWithStatus({
|
||||||
const { selectedAlertmanager, isGrafanaAlertmanager } = useAlertmanager();
|
alertmanager,
|
||||||
|
fetchStatuses,
|
||||||
const defaultOptions = {
|
fetchPolicies,
|
||||||
refetchOnFocus: true,
|
}: GrafanaFetchOptions & BaseAlertmanagerArgs) {
|
||||||
refetchOnReconnect: true,
|
const isGrafanaAlertmanager = alertmanager === GRAFANA_RULES_SOURCE_NAME;
|
||||||
};
|
const grafanaResponse = useGrafanaContactPoints({
|
||||||
|
|
||||||
// fetch receiver status if we're dealing with a Grafana Managed Alertmanager
|
|
||||||
const fetchContactPointsStatus = useGetContactPointsStatusQuery(undefined, {
|
|
||||||
...defaultOptions,
|
|
||||||
// re-fetch status every so often for up-to-date information
|
|
||||||
pollingInterval: RECEIVER_STATUS_POLLING_INTERVAL,
|
|
||||||
// skip fetching receiver statuses if not Grafana AM
|
|
||||||
skip: !isGrafanaAlertmanager,
|
skip: !isGrafanaAlertmanager,
|
||||||
|
fetchStatuses,
|
||||||
|
fetchPolicies,
|
||||||
});
|
});
|
||||||
|
|
||||||
// fetch notifier metadata from the Grafana API if we're using a Grafana AM – this will be used to add additional
|
const alertmanagerConfigResponse = useGetAlertmanagerConfigurationQuery(alertmanager, {
|
||||||
// metadata and canonical names to the receiver
|
|
||||||
const fetchReceiverMetadata = useGrafanaNotifiersQuery(undefined, {
|
|
||||||
skip: !isGrafanaAlertmanager,
|
|
||||||
});
|
|
||||||
|
|
||||||
// if the OnCall plugin is installed, fetch its list of integrations so we can match those to the Grafana Managed contact points
|
|
||||||
const { data: onCallMetadata, isLoading: onCallPluginIntegrationsLoading } = useOnCallIntegrations({
|
|
||||||
skip: !isGrafanaAlertmanager,
|
|
||||||
});
|
|
||||||
|
|
||||||
// fetch the latest config from the Alertmanager
|
|
||||||
// we use this endpoint only when we need to get the number of policies
|
|
||||||
const fetchAlertmanagerConfiguration = useGetAlertmanagerConfigurationQuery(selectedAlertmanager!, {
|
|
||||||
...defaultOptions,
|
...defaultOptions,
|
||||||
selectFromResult: (result) => ({
|
selectFromResult: (result) => ({
|
||||||
...result,
|
...result,
|
||||||
contactPoints: result.data
|
contactPoints: result.data
|
||||||
? enhanceContactPointsWithMetadata(
|
? enhanceContactPointsWithMetadata({
|
||||||
fetchContactPointsStatus.data,
|
notifiers: cloudNotifierTypes,
|
||||||
isGrafanaAlertmanager ? fetchReceiverMetadata.data : cloudNotifierTypes,
|
contactPoints: result.data.alertmanager_config.receivers ?? [],
|
||||||
onCallMetadata,
|
alertmanagerConfiguration: result.data,
|
||||||
result.data.alertmanager_config.receivers ?? [],
|
})
|
||||||
result.data
|
|
||||||
)
|
|
||||||
: [],
|
: [],
|
||||||
}),
|
}),
|
||||||
|
skip: isGrafanaAlertmanager,
|
||||||
});
|
});
|
||||||
|
|
||||||
// we will fail silently for fetching OnCall plugin status and integrations
|
return isGrafanaAlertmanager ? grafanaResponse : alertmanagerConfigResponse;
|
||||||
const error = fetchAlertmanagerConfiguration.error || fetchContactPointsStatus.error;
|
|
||||||
const isLoading =
|
|
||||||
fetchAlertmanagerConfiguration.isLoading || fetchContactPointsStatus.isLoading || onCallPluginIntegrationsLoading;
|
|
||||||
|
|
||||||
return {
|
|
||||||
error,
|
|
||||||
isLoading,
|
|
||||||
contactPoints: fetchAlertmanagerConfiguration.contactPoints,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useDeleteContactPoint(selectedAlertmanager: string) {
|
export function useDeleteContactPoint(selectedAlertmanager: string) {
|
||||||
|
@ -102,6 +102,14 @@ export interface ContactPointWithMetadata extends GrafanaManagedContactPoint {
|
|||||||
grafana_managed_receiver_configs: ReceiverConfigWithMetadata[];
|
grafana_managed_receiver_configs: ReceiverConfigWithMetadata[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EnhanceContactPointsArgs = {
|
||||||
|
status?: ReceiversStateDTO[];
|
||||||
|
notifiers?: NotifierDTO[];
|
||||||
|
onCallIntegrations?: OnCallIntegrationDTO[] | undefined | null;
|
||||||
|
contactPoints: Receiver[];
|
||||||
|
alertmanagerConfiguration?: AlertManagerCortexConfig;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function adds the status information for each of the integrations (contact point types) in a contact point
|
* This function adds the status information for each of the integrations (contact point types) in a contact point
|
||||||
* 1. we iterate over all contact points
|
* 1. we iterate over all contact points
|
||||||
@ -110,13 +118,13 @@ export interface ContactPointWithMetadata extends GrafanaManagedContactPoint {
|
|||||||
* alertmanagerConfiguration: optional as is passed when we need to get number of policies for each contact point
|
* alertmanagerConfiguration: optional as is passed when we need to get number of policies for each contact point
|
||||||
* and we prefer using the data from the read-only endpoint.
|
* and we prefer using the data from the read-only endpoint.
|
||||||
*/
|
*/
|
||||||
export function enhanceContactPointsWithMetadata(
|
export function enhanceContactPointsWithMetadata({
|
||||||
status: ReceiversStateDTO[] = [],
|
status = [],
|
||||||
notifiers: NotifierDTO[] = [],
|
notifiers = [],
|
||||||
onCallIntegrations: OnCallIntegrationDTO[] | undefined | null,
|
onCallIntegrations,
|
||||||
contactPoints: Receiver[],
|
contactPoints,
|
||||||
alertmanagerConfiguration?: AlertManagerCortexConfig
|
alertmanagerConfiguration,
|
||||||
): ContactPointWithMetadata[] {
|
}: EnhanceContactPointsArgs): ContactPointWithMetadata[] {
|
||||||
// compute the entire inherited tree before finding what notification policies are using a particular contact point
|
// compute the entire inherited tree before finding what notification policies are using a particular contact point
|
||||||
const fullyInheritedTree = computeInheritedTree(alertmanagerConfiguration?.alertmanager_config?.route ?? {});
|
const fullyInheritedTree = computeInheritedTree(alertmanagerConfiguration?.alertmanager_config?.route ?? {});
|
||||||
const usedContactPoints = getUsedContactPoints(fullyInheritedTree);
|
const usedContactPoints = getUsedContactPoints(fullyInheritedTree);
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
ReadNamespacedTimeIntervalApiResponse,
|
ReadNamespacedTimeIntervalApiResponse,
|
||||||
} from 'app/features/alerting/unified/openapi/timeIntervalsApi.gen';
|
} from 'app/features/alerting/unified/openapi/timeIntervalsApi.gen';
|
||||||
import { deleteMuteTimingAction, updateAlertManagerConfigAction } from 'app/features/alerting/unified/state/actions';
|
import { deleteMuteTimingAction, updateAlertManagerConfigAction } from 'app/features/alerting/unified/state/actions';
|
||||||
|
import { BaseAlertmanagerArgs } from 'app/features/alerting/unified/types/hooks';
|
||||||
import { renameMuteTimings } from 'app/features/alerting/unified/utils/alertmanager';
|
import { renameMuteTimings } from 'app/features/alerting/unified/utils/alertmanager';
|
||||||
import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource';
|
import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/datasource';
|
||||||
import { MuteTimeInterval } from 'app/plugins/datasource/alertmanager/types';
|
import { MuteTimeInterval } from 'app/plugins/datasource/alertmanager/types';
|
||||||
@ -27,15 +28,6 @@ const {
|
|||||||
useDeleteNamespacedTimeIntervalMutation,
|
useDeleteNamespacedTimeIntervalMutation,
|
||||||
} = timeIntervalsApi;
|
} = timeIntervalsApi;
|
||||||
|
|
||||||
type BaseAlertmanagerArgs = {
|
|
||||||
/**
|
|
||||||
* Name of alertmanager being used for mute timings management.
|
|
||||||
*
|
|
||||||
* Hooks will behave differently depending on whether this is `grafana` or an external alertmanager
|
|
||||||
*/
|
|
||||||
alertmanager: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alertmanager mute time interval, with optional additional metadata
|
* Alertmanager mute time interval, with optional additional metadata
|
||||||
* (returned in the case of K8S API implementation)
|
* (returned in the case of K8S API implementation)
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { Select, SelectCommonProps, Text, Stack } from '@grafana/ui';
|
import { Select, SelectCommonProps, Text, Stack } from '@grafana/ui';
|
||||||
|
import { useAlertmanager } from 'app/features/alerting/unified/state/AlertmanagerContext';
|
||||||
|
|
||||||
import { RECEIVER_META_KEY, RECEIVER_PLUGIN_META_KEY } from '../contact-points/constants';
|
import { RECEIVER_META_KEY, RECEIVER_PLUGIN_META_KEY } from '../contact-points/constants';
|
||||||
import { useContactPointsWithStatus } from '../contact-points/useContactPoints';
|
import { useContactPointsWithStatus } from '../contact-points/useContactPoints';
|
||||||
import { ReceiverConfigWithMetadata } from '../contact-points/utils';
|
import { ReceiverConfigWithMetadata } from '../contact-points/utils';
|
||||||
|
|
||||||
export const ContactPointSelector = (props: SelectCommonProps<string>) => {
|
export const ContactPointSelector = (props: SelectCommonProps<string>) => {
|
||||||
const { contactPoints, isLoading, error } = useContactPointsWithStatus();
|
const { selectedAlertmanager } = useAlertmanager();
|
||||||
|
const { contactPoints, isLoading, error } = useContactPointsWithStatus({ alertmanager: selectedAlertmanager! });
|
||||||
|
|
||||||
// TODO error handling
|
// TODO error handling
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -8,7 +8,7 @@ import { RuleFormValues } from 'app/features/alerting/unified/types/rule-form';
|
|||||||
import { AlertManagerDataSource } from 'app/features/alerting/unified/utils/datasource';
|
import { AlertManagerDataSource } from 'app/features/alerting/unified/utils/datasource';
|
||||||
|
|
||||||
import { ContactPointReceiverSummary } from '../../../contact-points/ContactPoint';
|
import { ContactPointReceiverSummary } from '../../../contact-points/ContactPoint';
|
||||||
import { useGetContactPoints } from '../../../contact-points/useContactPoints';
|
import { useGrafanaContactPoints } from '../../../contact-points/useContactPoints';
|
||||||
import { ContactPointWithMetadata } from '../../../contact-points/utils';
|
import { ContactPointWithMetadata } from '../../../contact-points/utils';
|
||||||
|
|
||||||
import { ContactPointDetails } from './contactPoint/ContactPointDetails';
|
import { ContactPointDetails } from './contactPoint/ContactPointDetails';
|
||||||
@ -29,7 +29,7 @@ export function AlertManagerManualRouting({ alertManager }: AlertManagerManualRo
|
|||||||
error: errorInContactPointStatus,
|
error: errorInContactPointStatus,
|
||||||
contactPoints,
|
contactPoints,
|
||||||
refetch: refetchReceivers,
|
refetch: refetchReceivers,
|
||||||
} = useGetContactPoints();
|
} = useGrafanaContactPoints();
|
||||||
|
|
||||||
const [selectedContactPointWithMetadata, setSelectedContactPointWithMetadata] = useState<
|
const [selectedContactPointWithMetadata, setSelectedContactPointWithMetadata] = useState<
|
||||||
ContactPointWithMetadata | undefined
|
ContactPointWithMetadata | undefined
|
||||||
|
16
public/app/features/alerting/unified/types/hooks.ts
Normal file
16
public/app/features/alerting/unified/types/hooks.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export type BaseAlertmanagerArgs = {
|
||||||
|
/**
|
||||||
|
* Name of alertmanager to use for config entity management
|
||||||
|
*
|
||||||
|
* Hooks will behave differently depending on whether this is `grafana` or an external alertmanager
|
||||||
|
*/
|
||||||
|
alertmanager: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Skippable = {
|
||||||
|
/**
|
||||||
|
* Should we skip requests altogether?
|
||||||
|
* Useful for cases where we want to conditionally call hook methods
|
||||||
|
*/
|
||||||
|
skip?: boolean;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user