diff --git a/public/app/features/alerting/unified/Silences.test.tsx b/public/app/features/alerting/unified/Silences.test.tsx
index e478cb8baea..4b5ade80ec8 100644
--- a/public/app/features/alerting/unified/Silences.test.tsx
+++ b/public/app/features/alerting/unified/Silences.test.tsx
@@ -15,6 +15,8 @@ import { SilenceState } from '../../../plugins/datasource/alertmanager/types';
import Silences from './Silences';
import { createOrUpdateSilence, fetchAlerts, fetchSilences } from './api/alertmanager';
import { grantUserPermissions, mockAlertmanagerAlert, mockDataSource, MockDataSourceSrv, mockSilence } from './mocks';
+import { AlertmanagerProvider } from './state/AlertmanagerContext';
+import { setupDataSources } from './testSetup/datasources';
import { parseMatchers } from './utils/alertmanager';
import { DataSourceType } from './utils/datasource';
@@ -37,7 +39,9 @@ const renderSilences = (location = '/alerting/silences/') => {
return render(
-
+
+
+
);
};
@@ -218,7 +222,7 @@ describe('Silence edit', () => {
beforeEach(() => {
setUserLogged(true);
- setDataSourceSrv(new MockDataSourceSrv(dataSources));
+ setupDataSources(dataSources.am);
});
it('Should not render createdBy if user is logged in and has a name', async () => {
@@ -325,4 +329,32 @@ describe('Silence edit', () => {
},
TEST_TIMEOUT
);
+
+ it(
+ 'silences page should contain alertmanager parameter after creating a silence',
+ async () => {
+ const user = userEvent.setup();
+
+ renderSilences(`${baseUrlPath}?alertmanager=Alertmanager`);
+ await waitFor(() => expect(ui.editor.durationField.query()).not.toBeNull());
+
+ await user.type(ui.editor.matcherName.getAll()[0], 'foo');
+ await user.type(ui.editor.matcherOperatorSelect.getAll()[0], '=');
+ await user.type(ui.editor.matcherValue.getAll()[0], 'bar');
+
+ await user.click(ui.editor.submit.get());
+
+ await waitFor(() =>
+ expect(mocks.api.createOrUpdateSilence).toHaveBeenCalledWith(
+ 'Alertmanager',
+ expect.objectContaining({
+ matchers: [{ isEqual: true, isRegex: false, name: 'foo', value: 'bar' }],
+ })
+ )
+ );
+
+ expect(locationService.getSearch().get('alertmanager')).toBe('Alertmanager');
+ },
+ TEST_TIMEOUT
+ );
});
diff --git a/public/app/features/alerting/unified/state/AlertmanagerContext.tsx b/public/app/features/alerting/unified/state/AlertmanagerContext.tsx
index 05fdc334d94..f2d6e774ce8 100644
--- a/public/app/features/alerting/unified/state/AlertmanagerContext.tsx
+++ b/public/app/features/alerting/unified/state/AlertmanagerContext.tsx
@@ -1,10 +1,10 @@
import * as React from 'react';
-import { useQueryParams } from 'app/core/hooks/useQueryParams';
import store from 'app/core/store';
import { AlertManagerDataSourceJsonData, AlertManagerImplementation } from 'app/plugins/datasource/alertmanager/types';
import { useAlertManagersByPermission } from '../hooks/useAlertManagerSources';
+import { useURLSearchParams } from '../hooks/useURLSearchParams';
import { ALERTMANAGER_NAME_LOCAL_STORAGE_KEY, ALERTMANAGER_NAME_QUERY_KEY } from '../utils/constants';
import {
AlertManagerDataSource,
@@ -30,7 +30,7 @@ interface Props extends React.PropsWithChildren {
}
const AlertmanagerProvider = ({ children, accessType, alertmanagerSourceName }: Props) => {
- const [queryParams, updateQueryParams] = useQueryParams();
+ const [queryParams, updateQueryParams] = useURLSearchParams();
const allAvailableAlertManagers = useAlertManagersByPermission(accessType);
const availableAlertManagers = allAvailableAlertManagers.availableInternalDataSources.concat(
allAvailableAlertManagers.availableExternalDataSources
@@ -44,7 +44,7 @@ const AlertmanagerProvider = ({ children, accessType, alertmanagerSourceName }:
if (selectedAlertManager === GRAFANA_RULES_SOURCE_NAME) {
store.delete(ALERTMANAGER_NAME_LOCAL_STORAGE_KEY);
- updateQueryParams({ [ALERTMANAGER_NAME_QUERY_KEY]: null });
+ updateQueryParams({ [ALERTMANAGER_NAME_QUERY_KEY]: undefined });
} else {
store.set(ALERTMANAGER_NAME_LOCAL_STORAGE_KEY, selectedAlertManager);
updateQueryParams({ [ALERTMANAGER_NAME_QUERY_KEY]: selectedAlertManager });
@@ -53,10 +53,19 @@ const AlertmanagerProvider = ({ children, accessType, alertmanagerSourceName }:
[availableAlertManagers, updateQueryParams]
);
- const sourceFromQuery = queryParams[ALERTMANAGER_NAME_QUERY_KEY];
+ const sourceFromQuery = queryParams.get(ALERTMANAGER_NAME_QUERY_KEY);
const sourceFromStore = store.get(ALERTMANAGER_NAME_LOCAL_STORAGE_KEY);
const defaultSource = GRAFANA_RULES_SOURCE_NAME;
+ // This overrides AM in the store to be in sync with the one in the URL
+ // When the user uses multiple tabs with different AMs, the store will be changing all the time
+ // It's safest to always use URLs with alertmanager query param
+ React.useEffect(() => {
+ if (sourceFromQuery && sourceFromQuery !== sourceFromStore) {
+ store.set(ALERTMANAGER_NAME_LOCAL_STORAGE_KEY, sourceFromQuery);
+ }
+ }, [sourceFromQuery, sourceFromStore]);
+
// queryParam > localStorage > default
const desiredAlertmanager = alertmanagerSourceName ?? sourceFromQuery ?? sourceFromStore ?? defaultSource;
const selectedAlertmanager = isAlertManagerAvailable(availableAlertManagers, desiredAlertmanager)
diff --git a/public/app/features/alerting/unified/state/actions.ts b/public/app/features/alerting/unified/state/actions.ts
index f6cb7a5e0a3..04dadc73769 100644
--- a/public/app/features/alerting/unified/state/actions.ts
+++ b/public/app/features/alerting/unified/state/actions.ts
@@ -575,7 +575,7 @@ export const createOrUpdateSilenceAction = createAsyncThunk {
await createOrUpdateSilence(alertManagerSourceName, payload);
if (exitOnSave) {
- locationService.push('/alerting/silences');
+ locationService.push(makeAMLink('/alerting/silences', alertManagerSourceName));
}
})()
),
diff --git a/public/app/features/alerting/unified/utils/misc.ts b/public/app/features/alerting/unified/utils/misc.ts
index d3051a0de69..1b0017f3601 100644
--- a/public/app/features/alerting/unified/utils/misc.ts
+++ b/public/app/features/alerting/unified/utils/misc.ts
@@ -105,7 +105,7 @@ export function makeAMLink(path: string, alertManagerName?: string, options?: UR
const search = new URLSearchParams(options);
if (alertManagerName) {
- search.append(ALERTMANAGER_NAME_QUERY_KEY, alertManagerName);
+ search.set(ALERTMANAGER_NAME_QUERY_KEY, alertManagerName);
}
return `${path}?${search.toString()}`;
}