Alerting: Ensure we fetch AM config before saving new configuration (#88458)

pull/88566/head
Tom Ratcliffe 12 months ago committed by GitHub
parent aec8412af9
commit dfd64ed469
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 37
      public/app/features/alerting/unified/Templates.test.tsx
  2. 1
      public/app/features/alerting/unified/components/receivers/TemplateForm.tsx
  3. 14
      public/app/features/alerting/unified/mocks/server/configure.ts
  4. 25
      public/app/features/alerting/unified/mocks/server/handlers/alertmanagers.ts
  5. 6
      public/app/features/alerting/unified/state/actions.ts

@ -1,18 +1,22 @@
import React from 'react';
import { render, screen } from 'test/test-utils';
import { render, screen, userEvent } from 'test/test-utils';
import { setupMswServer } from 'app/features/alerting/unified/mockApi';
import { setGrafanaAlertmanagerConfig } from 'app/features/alerting/unified/mocks/server/configure';
import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types';
import { AccessControlAction } from 'app/types';
import Templates from './Templates';
import setupGrafanaManagedServer from './components/contact-points/__mocks__/grafanaManagedServer';
import { grantUserPermissions } from './mocks';
const server = setupMswServer();
jest.mock('app/core/components/AppChrome/AppChromeUpdate', () => ({
AppChromeUpdate: ({ actions }: { actions: React.ReactNode }) => <div>{actions}</div>,
}));
setupMswServer();
beforeEach(() => {
grantUserPermissions([AccessControlAction.AlertingNotificationsRead, AccessControlAction.AlertingNotificationsWrite]);
setupGrafanaManagedServer(server);
});
describe('Templates routes', () => {
@ -25,4 +29,29 @@ describe('Templates routes', () => {
expect(await screen.findByText('Edit payload')).toBeInTheDocument();
});
it('shows an error when remote AM config has been updated ', async () => {
const originalConfig: AlertManagerCortexConfig = {
template_files: {},
alertmanager_config: {},
};
setGrafanaAlertmanagerConfig(originalConfig);
const user = userEvent.setup();
render(<Templates />, {
historyOptions: {
initialEntries: ['/alerting/notifications/templates/new'],
},
});
await user.type(await screen.findByLabelText(/template name/i), 'a');
// Once the user has loaded the page and started creating their template,
// update the API behaviour as if another user has also edited the config and added something in
setGrafanaAlertmanagerConfig({ ...originalConfig, template_files: { a: 'b' } });
await user.click(screen.getByRole('button', { name: /save/i }));
expect(await screen.findByText(/a newer alertmanager configuration is available/i)).toBeInTheDocument();
});
});

@ -220,6 +220,7 @@ export const TemplateForm = ({ existing, alertManagerSourceName, config, provena
placeholder="Give your template a name"
width={42}
autoFocus={true}
id="new-template-name"
/>
</InlineField>

@ -1,8 +1,11 @@
import server from 'app/features/alerting/unified/mockApi';
import { mockFolder } from 'app/features/alerting/unified/mocks';
import { grafanaAlertingConfigurationStatusHandler } from 'app/features/alerting/unified/mocks/server/handlers/alertmanagers';
import {
getGrafanaAlertmanagerConfigHandler,
grafanaAlertingConfigurationStatusHandler,
} from 'app/features/alerting/unified/mocks/server/handlers/alertmanagers';
import { getFolderHandler } from 'app/features/alerting/unified/mocks/server/handlers/folders';
import { AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types';
import { AlertManagerCortexConfig, AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types';
import { FolderDTO } from 'app/types';
/**
@ -23,3 +26,10 @@ export const setAlertmanagerChoices = (alertmanagersChoice: AlertmanagerChoice,
export const setFolderAccessControl = (accessControl: FolderDTO['accessControl']) => {
server.use(getFolderHandler(mockFolder({ hasAcl: true, accessControl })));
};
/**
* Makes the mock server respond with different Grafana Alertmanager config
*/
export const setGrafanaAlertmanagerConfig = (config: AlertManagerCortexConfig) => {
server.use(getGrafanaAlertmanagerConfigHandler(config));
};

@ -1,9 +1,10 @@
import { http, HttpResponse } from 'msw';
import alertmanagerConfigMock from 'app/features/alerting/unified/components/contact-points/__mocks__/alertmanager.config.mock.json';
import { MOCK_SILENCE_ID_EXISTING, mockAlertmanagerAlert } from 'app/features/alerting/unified/mocks';
import { defaultGrafanaAlertingConfigurationStatusResponse } from 'app/features/alerting/unified/mocks/alertmanagerApi';
import { MOCK_DATASOURCE_UID_BROKEN_ALERTMANAGER } from 'app/features/alerting/unified/mocks/server/handlers/datasources';
import { AlertState } from 'app/plugins/datasource/alertmanager/types';
import { AlertManagerCortexConfig, AlertState } from 'app/plugins/datasource/alertmanager/types';
export const grafanaAlertingConfigurationStatusHandler = (
response = defaultGrafanaAlertingConfigurationStatusResponse
@ -26,5 +27,25 @@ export const alertmanagerAlertsListHandler = () =>
]);
});
const handlers = [alertmanagerAlertsListHandler(), grafanaAlertingConfigurationStatusHandler()];
export const getGrafanaAlertmanagerConfigHandler = (config: AlertManagerCortexConfig = alertmanagerConfigMock) =>
http.get('/api/alertmanager/grafana/config/api/v1/alerts', () => HttpResponse.json(config));
const updateGrafanaAlertmanagerConfigHandler = () =>
http.post('/api/alertmanager/grafana/config/api/v1/alerts', () =>
HttpResponse.json({ message: 'configuration created' })
);
const getGrafanaAlertmanagerTemplatePreview = () =>
http.post('/api/alertmanager/grafana/config/api/v1/templates/test', () =>
// TODO: Scaffold out template preview response as needed by tests
HttpResponse.json({})
);
const handlers = [
alertmanagerAlertsListHandler(),
grafanaAlertingConfigurationStatusHandler(),
getGrafanaAlertmanagerConfigHandler(),
updateGrafanaAlertmanagerConfigHandler(),
getGrafanaAlertmanagerTemplatePreview(),
];
export default handlers;

@ -491,7 +491,11 @@ export const updateAlertManagerConfigAction = createAsyncThunk<void, UpdateAlert
withSerializedError(
(async () => {
const latestConfig = await thunkAPI
.dispatch(alertmanagerApi.endpoints.getAlertmanagerConfiguration.initiate(alertManagerSourceName))
.dispatch(
alertmanagerApi.endpoints.getAlertmanagerConfiguration.initiate(alertManagerSourceName, {
forceRefetch: true,
})
)
.unwrap();
const isLatestConfigEmpty = isEmpty(latestConfig.alertmanager_config) && isEmpty(latestConfig.template_files);

Loading…
Cancel
Save