mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Don't redirect after failed contact point creation (#92761)
This commit is contained in:
parent
91cbaa4afe
commit
9f5dca96f2
@ -410,10 +410,12 @@ export const useCreateContactPoint = ({ alertmanager }: BaseAlertmanagerArgs) =>
|
||||
oldConfig: config,
|
||||
alertManagerSourceName: alertmanager,
|
||||
})
|
||||
).then(() => {
|
||||
dispatch(alertingApi.util.invalidateTags(['AlertmanagerConfiguration', 'ContactPoint', 'ContactPointsStatus']));
|
||||
dispatch(generatedReceiversApi.util.invalidateTags(['Receiver']));
|
||||
});
|
||||
)
|
||||
.unwrap()
|
||||
.then(() => {
|
||||
dispatch(alertingApi.util.invalidateTags(['AlertmanagerConfiguration', 'ContactPoint', 'ContactPointsStatus']));
|
||||
dispatch(generatedReceiversApi.util.invalidateTags(['Receiver']));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { render, screen } from 'test/test-utils';
|
||||
import { byLabelText, byPlaceholderText, byRole, byTestId } from 'testing-library-selector';
|
||||
|
||||
import { config } from '@grafana/runtime';
|
||||
import { makeGrafanaAlertmanagerConfigUpdateFail } from 'app/features/alerting/unified/mocks/server/configure';
|
||||
import { captureRequests } from 'app/features/alerting/unified/mocks/server/events';
|
||||
import { AccessControlAction } from 'app/types';
|
||||
|
||||
@ -106,6 +107,20 @@ describe('alerting API server disabled', () => {
|
||||
expect([testBody]).toMatchSnapshot();
|
||||
expect([saveBody]).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('does not redirect when creating contact point and API errors', async () => {
|
||||
makeGrafanaAlertmanagerConfigUpdateFail();
|
||||
const { user } = renderForm();
|
||||
|
||||
await user.type(await ui.inputs.name.find(), 'receiver that should fail');
|
||||
const email = ui.inputs.email.addresses.get();
|
||||
await user.clear(email);
|
||||
await user.type(email, 'tester@grafana.com');
|
||||
|
||||
await user.click(ui.saveContactButton.get());
|
||||
|
||||
expect(screen.queryByText(/redirected/i)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
const ui = {
|
||||
|
@ -54,12 +54,16 @@ export const CloudReceiverForm = ({ contactPoint, alertManagerSourceName, readOn
|
||||
|
||||
const onSubmit = async (values: ReceiverFormValues<CloudChannelValues>) => {
|
||||
const newReceiver = formValuesToCloudReceiver(values, defaultChannelValues);
|
||||
if (editMode) {
|
||||
await updateContactPoint({ contactPoint: newReceiver, originalName: contactPoint!.name });
|
||||
} else {
|
||||
await createContactPoint({ contactPoint: newReceiver });
|
||||
try {
|
||||
if (editMode) {
|
||||
await updateContactPoint({ contactPoint: newReceiver, originalName: contactPoint!.name });
|
||||
} else {
|
||||
await createContactPoint({ contactPoint: newReceiver });
|
||||
}
|
||||
locationService.push('/alerting/notifications');
|
||||
} catch (error) {
|
||||
// React form validation will handle this for us
|
||||
}
|
||||
locationService.push('/alerting/notifications');
|
||||
};
|
||||
|
||||
// this basically checks if we can manage the selected alert manager data source, either because it's a Grafana Managed one
|
||||
|
@ -81,17 +81,21 @@ export const GrafanaReceiverForm = ({ contactPoint, readOnly = false, editMode }
|
||||
|
||||
const onSubmit = async (values: ReceiverFormValues<GrafanaChannelValues>) => {
|
||||
const newReceiver = formValuesToGrafanaReceiver(values, id2original, defaultChannelValues, grafanaNotifiers);
|
||||
if (editMode) {
|
||||
await updateContactPoint({
|
||||
contactPoint: newReceiver,
|
||||
id: contactPoint!.id,
|
||||
resourceVersion: contactPoint?.metadata?.resourceVersion,
|
||||
originalName: contactPoint?.name,
|
||||
});
|
||||
} else {
|
||||
await createContactPoint({ contactPoint: newReceiver });
|
||||
try {
|
||||
if (editMode) {
|
||||
await updateContactPoint({
|
||||
contactPoint: newReceiver,
|
||||
id: contactPoint!.id,
|
||||
resourceVersion: contactPoint?.metadata?.resourceVersion,
|
||||
originalName: contactPoint?.name,
|
||||
});
|
||||
} else {
|
||||
await createContactPoint({ contactPoint: newReceiver });
|
||||
}
|
||||
locationService.push('/alerting/notifications');
|
||||
} catch (error) {
|
||||
// React form validation will handle this for us
|
||||
}
|
||||
locationService.push('/alerting/notifications');
|
||||
};
|
||||
|
||||
const onTestChannel = (values: GrafanaChannelValues) => {
|
||||
|
@ -4,9 +4,11 @@ import { config } from '@grafana/runtime';
|
||||
import server, { mockFeatureDiscoveryApi } from 'app/features/alerting/unified/mockApi';
|
||||
import { mockDataSource, mockFolder } from 'app/features/alerting/unified/mocks';
|
||||
import {
|
||||
ALERTMANAGER_UPDATE_ERROR_RESPONSE,
|
||||
getAlertmanagerConfigHandler,
|
||||
getGrafanaAlertmanagerConfigHandler,
|
||||
grafanaAlertingConfigurationStatusHandler,
|
||||
updateGrafanaAlertmanagerConfigHandler,
|
||||
} from 'app/features/alerting/unified/mocks/server/handlers/alertmanagers';
|
||||
import { getFolderHandler } from 'app/features/alerting/unified/mocks/server/handlers/folders';
|
||||
import { listNamespacedTimeIntervalHandler } from 'app/features/alerting/unified/mocks/server/handlers/k8s/timeIntervals.k8s';
|
||||
@ -126,3 +128,8 @@ export const removePlugin = (pluginId: string) => {
|
||||
export const disablePlugin = (pluginId: SupportedPlugin) => {
|
||||
server.use(getDisabledPluginHandler(pluginId));
|
||||
};
|
||||
|
||||
/** Make alertmanager config update fail */
|
||||
export const makeGrafanaAlertmanagerConfigUpdateFail = () => {
|
||||
server.use(updateGrafanaAlertmanagerConfigHandler(ALERTMANAGER_UPDATE_ERROR_RESPONSE));
|
||||
};
|
||||
|
@ -35,7 +35,7 @@ export const getGrafanaAlertmanagerConfigHandler = (config: AlertManagerCortexCo
|
||||
export const getAlertmanagerConfigHandler = (config: AlertManagerCortexConfig = alertmanagerConfigMock) =>
|
||||
http.get('/api/alertmanager/:name/config/api/v1/alerts', () => HttpResponse.json(config));
|
||||
|
||||
const alertmanagerUpdateError = HttpResponse.json({ message: 'bad request' }, { status: 400 });
|
||||
export const ALERTMANAGER_UPDATE_ERROR_RESPONSE = HttpResponse.json({ message: 'bad request' }, { status: 400 });
|
||||
|
||||
/** Perform some basic validation on the config that we expect the backend to also do */
|
||||
const validateGrafanaAlertmanagerConfig = (config: AlertManagerCortexConfig) => {
|
||||
@ -46,27 +46,28 @@ const validateGrafanaAlertmanagerConfig = (config: AlertManagerCortexConfig) =>
|
||||
const intervalsByName = new Set(intervals.map((interval) => interval.name));
|
||||
const duplicatedIntervals = intervalsByName.size !== intervals.length;
|
||||
|
||||
let routesReferencingMissingMuteTimings = false;
|
||||
|
||||
if (route) {
|
||||
const routesReferencingMissingMuteTimings = Boolean(
|
||||
routesReferencingMissingMuteTimings = Boolean(
|
||||
route.routes?.find((route) => {
|
||||
return route.mute_time_intervals?.some((name) => !intervalsByName.has(name));
|
||||
})
|
||||
);
|
||||
|
||||
if (routesReferencingMissingMuteTimings) {
|
||||
return alertmanagerUpdateError;
|
||||
}
|
||||
}
|
||||
|
||||
if (duplicatedIntervals) {
|
||||
return alertmanagerUpdateError;
|
||||
if (routesReferencingMissingMuteTimings || duplicatedIntervals) {
|
||||
return ALERTMANAGER_UPDATE_ERROR_RESPONSE;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const updateGrafanaAlertmanagerConfigHandler = () =>
|
||||
export const updateGrafanaAlertmanagerConfigHandler = (responseOverride?: typeof ALERTMANAGER_UPDATE_ERROR_RESPONSE) =>
|
||||
http.post('/api/alertmanager/grafana/config/api/v1/alerts', async ({ request }) => {
|
||||
if (responseOverride) {
|
||||
return responseOverride;
|
||||
}
|
||||
const body: AlertManagerCortexConfig = await request.clone().json();
|
||||
const potentialError = validateGrafanaAlertmanagerConfig(body);
|
||||
return potentialError ? potentialError : HttpResponse.json({ message: 'configuration created' });
|
||||
|
Loading…
Reference in New Issue
Block a user