Alerting: Get oncall metada only when we have alert manager configuration data (#85622)

* Get oncall metada from url in settings only when we have alert manager configuration

* Add test in useContactPointsWithStatus hook

* Fix tests
pull/85594/head
Sonia Aguilar 1 year ago committed by GitHub
parent 8a15ed42ae
commit e234d098e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 12
      public/app/features/alerting/unified/components/contact-points/ContactPoints.test.tsx
  2. 13
      public/app/features/alerting/unified/components/contact-points/__mocks__/alertmanager.config.mock.json
  3. 13
      public/app/features/alerting/unified/components/contact-points/__snapshots__/NewContactPoint.test.tsx.snap
  4. 197
      public/app/features/alerting/unified/components/contact-points/__snapshots__/useContactPoints.test.tsx.snap
  5. 48
      public/app/features/alerting/unified/components/contact-points/useContactPoints.test.tsx
  6. 7
      public/app/features/alerting/unified/components/contact-points/utils.ts
  7. 9
      public/app/features/alerting/unified/components/receivers/grafanaAppReceivers/useReceiversMetadata.ts
  8. 4
      public/app/features/alerting/unified/mockApi.ts

@ -65,7 +65,7 @@ describe('contact points', () => {
});
expect(screen.getByText('grafana-default-email')).toBeInTheDocument();
expect(screen.getAllByTestId('contact-point')).toHaveLength(4);
expect(screen.getAllByTestId('contact-point')).toHaveLength(5);
// check for available actions – our mock 4 contact points, 1 of them is provisioned
expect(screen.getByRole('link', { name: 'add contact point' })).toBeInTheDocument();
@ -73,20 +73,20 @@ describe('contact points', () => {
// 2 of them are unused by routes in the mock response
const unusedBadge = screen.getAllByLabelText('unused');
expect(unusedBadge).toHaveLength(2);
expect(unusedBadge).toHaveLength(3);
const viewProvisioned = screen.getByRole('link', { name: 'view-action' });
expect(viewProvisioned).toBeInTheDocument();
expect(viewProvisioned).not.toBeDisabled();
const editButtons = screen.getAllByRole('link', { name: 'edit-action' });
expect(editButtons).toHaveLength(3);
expect(editButtons).toHaveLength(4);
editButtons.forEach((button) => {
expect(button).not.toBeDisabled();
});
const moreActionsButtons = screen.getAllByRole('button', { name: 'more-actions' });
expect(moreActionsButtons).toHaveLength(4);
expect(moreActionsButtons).toHaveLength(5);
moreActionsButtons.forEach((button) => {
expect(button).not.toBeDisabled();
});
@ -115,11 +115,11 @@ describe('contact points', () => {
// there should be view buttons though
const viewButtons = screen.getAllByRole('link', { name: 'view-action' });
expect(viewButtons).toHaveLength(4);
expect(viewButtons).toHaveLength(5);
// delete should be disabled in the "more" actions
const moreButtons = screen.queryAllByRole('button', { name: 'more-actions' });
expect(moreButtons).toHaveLength(4);
expect(moreButtons).toHaveLength(5);
// check if all of the delete buttons are disabled
for await (const button of moreButtons) {

@ -73,6 +73,19 @@
"secureFields": { "token": true }
}
]
},
{
"name": "OnCall Conctact point",
"grafana_managed_receiver_configs": [
{
"name": "Oncall-integration",
"type": "oncall",
"settings": {
"url": "https://oncall-endpoint.example.com"
},
"disableResolveMessage": false
}
]
}
]
}

@ -115,6 +115,19 @@ exports[`should be able to test and save a receiver 2`] = `
],
"name": "Slack with multiple channels",
},
{
"grafana_managed_receiver_configs": [
{
"disableResolveMessage": false,
"name": "Oncall-integration",
"settings": {
"url": "https://oncall-endpoint.example.com",
},
"type": "oncall",
},
],
"name": "OnCall Conctact point",
},
{
"grafana_managed_receiver_configs": [
{

@ -60,6 +60,32 @@ exports[`useContactPoints should return contact points with status 1`] = `
"name": "lotsa-emails",
"numberOfPolicies": 0,
},
{
"grafana_managed_receiver_configs": [
{
"disableResolveMessage": false,
"name": "Oncall-integration",
"settings": {
"url": "https://oncall-endpoint.example.com",
},
"type": "oncall",
Symbol(receiver_status): undefined,
Symbol(receiver_metadata): {
"description": undefined,
"name": "Oncall",
},
Symbol(receiver_plugin_metadata): {
"description": "grafana-integration",
"externalUrl": "/a/grafana-oncall-app/integrations/ABC123",
"icon": "public/img/alerting/oncall_logo.svg",
"title": "Grafana OnCall",
"warning": undefined,
},
},
],
"name": "OnCall Conctact point",
"numberOfPolicies": 0,
},
{
"grafana_managed_receiver_configs": [
{
@ -147,3 +173,174 @@ exports[`useContactPoints should return contact points with status 1`] = `
"refetchReceivers": [Function],
}
`;
exports[`useContactPoints when having oncall plugin installed and no alert manager config data should return contact points with oncall metadata 1`] = `
{
"contactPoints": [
{
"grafana_managed_receiver_configs": [
{
"disableResolveMessage": false,
"name": "grafana-default-email",
"secureFields": {},
"settings": {
"addresses": "gilles.demey@grafana.com",
"singleEmail": false,
},
"type": "email",
"uid": "xeKQrBrnk",
Symbol(receiver_status): {
"lastNotifyAttempt": "2023-07-02T21:35:34.841+02:00",
"lastNotifyAttemptDuration": "1ms",
"lastNotifyAttemptError": "failed to send notification to email addresses: gilles.demey@grafana.com: dial tcp 192.168.1.21:1025: connect: connection refused",
"name": "email",
"sendResolved": true,
},
Symbol(receiver_metadata): {
"description": "Sends notifications using Grafana server configured SMTP settings",
"name": "Email",
},
Symbol(receiver_plugin_metadata): undefined,
},
],
"name": "grafana-default-email",
"numberOfPolicies": undefined,
},
{
"grafana_managed_receiver_configs": [
{
"disableResolveMessage": false,
"name": "lotsa-emails",
"secureFields": {},
"settings": {
"addresses": "gilles.demey+1@grafana.com, gilles.demey+2@grafana.com, gilles.demey+3@grafana.com, gilles.demey+4@grafana.com",
"singleEmail": false,
},
"type": "email",
"uid": "af306c96-35a2-4d6e-908a-4993e245dbb2",
Symbol(receiver_status): {
"lastNotifyAttempt": "",
"lastNotifyAttemptDuration": "",
"name": "email",
"sendResolved": true,
},
Symbol(receiver_metadata): {
"description": "Sends notifications using Grafana server configured SMTP settings",
"name": "Email",
},
Symbol(receiver_plugin_metadata): undefined,
},
],
"name": "lotsa-emails",
"numberOfPolicies": undefined,
},
{
"grafana_managed_receiver_configs": [
{
"disableResolveMessage": false,
"name": "Oncall-integration",
"settings": {
"url": "https://oncall-endpoint.example.com",
},
"type": "oncall",
Symbol(receiver_status): undefined,
Symbol(receiver_metadata): {
"description": undefined,
"name": "Oncall",
},
Symbol(receiver_plugin_metadata): {
"icon": "public/img/alerting/oncall_logo.svg",
"title": "Grafana OnCall",
},
},
],
"name": "OnCall Conctact point",
"numberOfPolicies": undefined,
},
{
"grafana_managed_receiver_configs": [
{
"disableResolveMessage": false,
"name": "provisioned-contact-point",
"provenance": "api",
"secureFields": {},
"settings": {
"addresses": "gilles.demey@grafana.com",
"singleEmail": false,
},
"type": "email",
"uid": "s8SdCVjnk",
Symbol(receiver_status): {
"lastNotifyAttempt": "",
"lastNotifyAttemptDuration": "",
"name": "email",
"sendResolved": true,
},
Symbol(receiver_metadata): {
"description": "Sends notifications using Grafana server configured SMTP settings",
"name": "Email",
},
Symbol(receiver_plugin_metadata): undefined,
},
],
"name": "provisioned-contact-point",
"numberOfPolicies": undefined,
},
{
"grafana_managed_receiver_configs": [
{
"disableResolveMessage": false,
"name": "Slack with multiple channels",
"secureFields": {
"token": true,
},
"settings": {
"recipient": "test-alerts",
},
"type": "slack",
"uid": "c02ad56a-31da-46b9-becb-4348ec0890fd",
Symbol(receiver_status): {
"lastNotifyAttempt": "",
"lastNotifyAttemptDuration": "",
"name": "slack",
"sendResolved": true,
},
Symbol(receiver_metadata): {
"description": "Sends notifications to Slack",
"name": "Slack",
},
Symbol(receiver_plugin_metadata): undefined,
},
{
"disableResolveMessage": false,
"name": "Slack with multiple channels",
"secureFields": {
"token": true,
},
"settings": {
"recipient": "test-alerts2",
},
"type": "slack",
"uid": "b286a3be-f690-49e2-8605-b075cbace2df",
Symbol(receiver_status): {
"lastNotifyAttempt": "",
"lastNotifyAttemptDuration": "",
"name": "slack",
"sendResolved": true,
},
Symbol(receiver_metadata): {
"description": "Sends notifications to Slack",
"name": "Slack",
},
Symbol(receiver_plugin_metadata): undefined,
},
],
"name": "Slack with multiple channels",
"numberOfPolicies": undefined,
},
],
"error": undefined,
"isLoading": false,
"refetchReceivers": [Function],
}
`;

@ -2,10 +2,12 @@ import { renderHook, waitFor } from '@testing-library/react';
import React from 'react';
import { TestProvider } from 'test/helpers/TestProvider';
import alertmanagerMock from 'app/features/alerting/unified/components/contact-points/__mocks__/alertmanager.config.mock.json';
import { AccessControlAction } from 'app/types';
import { setupMswServer } from '../../mockApi';
import { grantUserPermissions } from '../../mocks';
import { ONCALL_INTEGRATION_V2_FEATURE } from '../../api/onCallApi';
import { mockApi, setupMswServer } from '../../mockApi';
import { grantUserPermissions, onCallPluginMetaMock } from '../../mocks';
import { AlertmanagerProvider } from '../../state/AlertmanagerContext';
import setupGrafanaManagedServer from './__mocks__/grafanaManagedServer';
@ -23,6 +25,16 @@ describe('useContactPoints', () => {
});
it('should return contact points with status', async () => {
mockApi(server).plugins.getPluginSettings({ ...onCallPluginMetaMock, enabled: true });
mockApi(server).oncall.features([ONCALL_INTEGRATION_V2_FEATURE]);
mockApi(server).oncall.getOnCallIntegrations([
{
display_name: 'grafana-integration',
value: 'ABC123',
integration_url: 'https://oncall-endpoint.example.com',
},
]);
mockApi(server).getContactPointsList(receivers);
const { result } = renderHook(() => useContactPointsWithStatus(), {
wrapper: ({ children }) => (
<TestProvider>
@ -32,6 +44,35 @@ describe('useContactPoints', () => {
</TestProvider>
),
});
await waitFor(() => {
expect(result.current.isLoading).toBe(false);
expect(result.current).toMatchSnapshot();
});
});
describe('when having oncall plugin installed and no alert manager config data', () => {
it('should return contact points with oncall metadata', async () => {
mockApi(server).plugins.getPluginSettings({ ...onCallPluginMetaMock, enabled: true });
mockApi(server).oncall.features([ONCALL_INTEGRATION_V2_FEATURE]);
mockApi(server).oncall.getOnCallIntegrations([
{
display_name: 'grafana-integration',
value: 'ABC123',
integration_url: 'https://oncall-endpoint.example.com',
},
]);
mockApi(server).getContactPointsList(receivers);
const { result } = renderHook(
() => useContactPointsWithStatus({ includePoliciesCount: false, receiverStatusPollingInterval: 0 }),
{
wrapper: ({ children }) => (
<TestProvider>
<AlertmanagerProvider accessType={'notification'} alertmanagerSourceName={'grafana'}>
{children}
</AlertmanagerProvider>
</TestProvider>
),
}
);
await waitFor(() => {
expect(result.current.isLoading).toBe(false);
@ -39,3 +80,6 @@ describe('useContactPoints', () => {
});
});
});
});
const receivers = JSON.parse(JSON.stringify(alertmanagerMock)).alertmanager_config.receivers;

@ -137,12 +137,17 @@ export function enhanceContactPointsWithMetadata(
alertmanagerConfiguration && usedContactPointsByName && (usedContactPointsByName[contactPoint.name] ?? 0),
grafana_managed_receiver_configs: receivers.map((receiver, index) => {
const isOnCallReceiver = receiver.type === ReceiverTypes.OnCall;
// if we don't have alertmanagerConfiguration we can't get the metadata for oncall receivers,
// because we don't have the url, as we are not using the alertmanager configuration
// but the contact points returned by the read only permissions contact points endpoint (/api/v1/notifications/receivers)
return {
...receiver,
[RECEIVER_STATUS_KEY]: statusForReceiver?.integrations[index],
[RECEIVER_META_KEY]: getNotifierMetadata(notifiers, receiver),
// if OnCall plugin is installed, we'll add it to the receiver's plugin metadata
[RECEIVER_PLUGIN_META_KEY]: isOnCallReceiver ? getOnCallMetadata(onCallIntegrations, receiver) : undefined,
[RECEIVER_PLUGIN_META_KEY]: isOnCallReceiver
? getOnCallMetadata(onCallIntegrations, receiver, Boolean(alertmanagerConfiguration))
: undefined,
};
}),
};

@ -16,15 +16,20 @@ export interface ReceiverPluginMetadata {
const onCallReceiverICon = GRAFANA_APP_RECEIVERS_SOURCE_IMAGE[SupportedPlugin.OnCall];
const onCallReceiverTitle = 'Grafana OnCall';
const onCallReceiverMeta: ReceiverPluginMetadata = {
export const onCallReceiverMeta: ReceiverPluginMetadata = {
title: onCallReceiverTitle,
icon: onCallReceiverICon,
};
export function getOnCallMetadata(
onCallIntegrations: OnCallIntegrationDTO[] | undefined | null,
receiver: GrafanaManagedReceiverConfig
receiver: GrafanaManagedReceiverConfig,
hasAlertManagerConfigData = true
): ReceiverPluginMetadata {
if (!hasAlertManagerConfigData) {
return onCallReceiverMeta;
}
// oncall status is still loading
if (onCallIntegrations === undefined) {
return onCallReceiverMeta;

@ -20,6 +20,7 @@ import {
AlertManagerCortexConfig,
AlertmanagerReceiver,
EmailConfig,
GrafanaManagedContactPoint,
GrafanaManagedReceiverConfig,
MatcherOperator,
Route,
@ -218,6 +219,9 @@ export function mockApi(server: SetupServer) {
server.use(http.get(`api/plugins/${response.id}/settings`, () => HttpResponse.json(response)));
},
},
getContactPointsList: (response: GrafanaManagedContactPoint[]) => {
server.use(http.get(`/api/v1/notifications/receivers`, () => HttpResponse.json(response)));
},
oncall: {
getOnCallIntegrations: (response: OnCallIntegrationDTO[]) => {

Loading…
Cancel
Save