diff --git a/public/app/features/alerting/unified/Settings.test.tsx b/public/app/features/alerting/unified/Settings.test.tsx
index 5fb3835d3e5..9d2ca68f3b2 100644
--- a/public/app/features/alerting/unified/Settings.test.tsx
+++ b/public/app/features/alerting/unified/Settings.test.tsx
@@ -24,8 +24,8 @@ const ui = {
builtInAlertmanagerSection: byText('Built-in Alertmanager'),
otherAlertmanagerSection: byText('Other Alertmanagers'),
+ alertmanagerCard: (name: string) => byTestId(`alertmanager-card-${name}`),
builtInAlertmanagerCard: byTestId('alertmanager-card-Grafana built-in'),
- otherAlertmanagerCard: (name: string) => byTestId(`alertmanager-card-${name}`),
statusReceiving: byText(/receiving grafana-managed alerts/i),
statusNotReceiving: byText(/not receiving/i),
@@ -34,7 +34,11 @@ const ui = {
editConfigurationButton: byRole('button', { name: /edit configuration/i }),
saveConfigurationButton: byRole('button', { name: /save/i }),
+ enableButton: byRole('button', { name: 'Enable' }),
+ disableButton: byRole('button', { name: 'Disable' }),
+
versionsTab: byRole('tab', { name: /versions/i }),
+ provisionedBadge: byText(/^Provisioned$/),
};
describe('Alerting settings', () => {
@@ -59,7 +63,7 @@ describe('Alerting settings', () => {
// check external altermanagers
DataSourcesResponse.forEach((ds) => {
// get the card for datasource
- const card = ui.otherAlertmanagerCard(ds.name).get();
+ const card = ui.alertmanagerCard(ds.name).get();
// expect link to data source, provisioned badge, type, and status
expect(within(card).getByRole('link', { name: ds.name })).toBeInTheDocument();
@@ -120,4 +124,26 @@ describe('Alerting settings', () => {
expect(screen.getByText(/last applied/i)).toBeInTheDocument();
});
});
+
+ it('should correctly render provisioned data sources', async () => {
+ render();
+
+ // wait for loading to be done
+ await waitFor(() => expect(ui.builtInAlertmanagerSection.get()).toBeInTheDocument());
+
+ // provisioned alertmanager card
+ const provisionedCard = ui.alertmanagerCard('Provisioned Mimir-based Alertmanager').get();
+ expect(ui.provisionedBadge.get(provisionedCard)).toBeInTheDocument();
+
+ // should still be editable
+ const editConfigButton = ui.editConfigurationButton.get(provisionedCard);
+ expect(editConfigButton).toBeInTheDocument();
+
+ // enable / disable should not be avaiable when provisioned
+ const enableButton = ui.enableButton.query(provisionedCard);
+ const disableButton = ui.disableButton.query(provisionedCard);
+
+ expect(enableButton).not.toBeInTheDocument();
+ expect(disableButton).not.toBeInTheDocument();
+ });
});
diff --git a/public/app/features/alerting/unified/components/settings/AlertmanagerCard.tsx b/public/app/features/alerting/unified/components/settings/AlertmanagerCard.tsx
index c692ce38839..76ef9d9606a 100644
--- a/public/app/features/alerting/unified/components/settings/AlertmanagerCard.tsx
+++ b/public/app/features/alerting/unified/components/settings/AlertmanagerCard.tsx
@@ -76,6 +76,7 @@ export function AlertmanagerCard({
{/* we'll use the "tags" area to append buttons and actions */}
+ {/* ⚠️ provisioned Data sources cannot have their "enable" / "disable" actions but we should still allow editing of the configuration */}
diff --git a/public/app/features/alerting/unified/components/settings/AlertmanagerConfig.test.tsx b/public/app/features/alerting/unified/components/settings/AlertmanagerConfig.test.tsx
index 26d3ce9a165..dd1af8d3380 100644
--- a/public/app/features/alerting/unified/components/settings/AlertmanagerConfig.test.tsx
+++ b/public/app/features/alerting/unified/components/settings/AlertmanagerConfig.test.tsx
@@ -14,7 +14,7 @@ import { AlertmanagerProvider } from '../../state/AlertmanagerContext';
import AlertmanagerConfig from './AlertmanagerConfig';
import {
EXTERNAL_VANILLA_ALERTMANAGER_UID,
- PROVISIONED_VANILLA_ALERTMANAGER_UID,
+ PROVISIONED_MIMIR_ALERTMANAGER_UID,
setupGrafanaManagedServer,
setupVanillaAlertmanagerServer,
} from './__mocks__/server';
@@ -96,11 +96,11 @@ describe('vanilla Alertmanager', () => {
expect(ui.resetButton.query()).not.toBeInTheDocument();
});
- it('should be read-only when provisioned Alertmanager', async () => {
- renderConfiguration(PROVISIONED_VANILLA_ALERTMANAGER_UID, {});
+ it('should not be read-only when Mimir Alertmanager', async () => {
+ renderConfiguration(PROVISIONED_MIMIR_ALERTMANAGER_UID, {});
expect(ui.cancelButton.get()).toBeInTheDocument();
- expect(ui.saveButton.query()).not.toBeInTheDocument();
- expect(ui.resetButton.query()).not.toBeInTheDocument();
+ expect(ui.saveButton.get()).toBeInTheDocument();
+ expect(ui.resetButton.get()).toBeInTheDocument();
});
});
diff --git a/public/app/features/alerting/unified/components/settings/AlertmanagerConfig.tsx b/public/app/features/alerting/unified/components/settings/AlertmanagerConfig.tsx
index 9177aff1c9e..109116f96b9 100644
--- a/public/app/features/alerting/unified/components/settings/AlertmanagerConfig.tsx
+++ b/public/app/features/alerting/unified/components/settings/AlertmanagerConfig.tsx
@@ -9,11 +9,7 @@ import { Alert, Button, CodeEditor, ConfirmModal, Stack, useStyles2 } from '@gra
import { reportFormErrors } from '../../Analytics';
import { useAlertmanagerConfig } from '../../hooks/useAlertmanagerConfig';
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
-import {
- GRAFANA_RULES_SOURCE_NAME,
- isProvisionedDataSource,
- isVanillaPrometheusAlertManagerDataSource,
-} from '../../utils/datasource';
+import { GRAFANA_RULES_SOURCE_NAME, isVanillaPrometheusAlertManagerDataSource } from '../../utils/datasource';
import { Spacer } from '../Spacer';
export interface FormValues {
@@ -32,9 +28,9 @@ export default function AlertmanagerConfig({ alertmanagerName, onDismiss, onSave
const { loading: isSaving, error: savingError } = useUnifiedAlertingSelector((state) => state.saveAMConfig);
const [showResetConfirmation, setShowResetConfirmation] = useState(false);
+ // ⚠️ provisioned data sources should not prevent the configuration from being edited
const immutableDataSource = alertmanagerName ? isVanillaPrometheusAlertManagerDataSource(alertmanagerName) : false;
- const provisionedDataSource = isProvisionedDataSource(alertmanagerName);
- const readOnly = immutableDataSource || provisionedDataSource;
+ const readOnly = immutableDataSource;
const isGrafanaManagedAlertmanager = alertmanagerName === GRAFANA_RULES_SOURCE_NAME;
const styles = useStyles2(getStyles);
diff --git a/public/app/features/alerting/unified/components/settings/ExternalAlertmanagers.tsx b/public/app/features/alerting/unified/components/settings/ExternalAlertmanagers.tsx
index 414cf4d1d95..f9f0541ca43 100644
--- a/public/app/features/alerting/unified/components/settings/ExternalAlertmanagers.tsx
+++ b/public/app/features/alerting/unified/components/settings/ExternalAlertmanagers.tsx
@@ -7,6 +7,7 @@ import { AlertmanagerChoice } from 'app/plugins/datasource/alertmanager/types';
import { ExternalAlertmanagerDataSourceWithStatus } from '../../hooks/useExternalAmSelector';
import {
isAlertmanagerDataSourceInterestedInAlerts,
+ isProvisionedDataSource,
isVanillaPrometheusAlertManagerDataSource,
} from '../../utils/datasource';
import { createUrl } from '../../utils/url';
@@ -44,9 +45,9 @@ export const ExternalAlertmanagers = ({ onEditConfiguration }: Props) => {
const { status } = alertmanager;
const isReceiving = isReceivingGrafanaAlerts(alertmanager);
- const isProvisioned = alertmanager.dataSourceSettings.readOnly === true;
- const isReadOnly =
- isProvisioned || isVanillaPrometheusAlertManagerDataSource(alertmanager.dataSourceSettings.name);
+ const isProvisioned = isProvisionedDataSource(alertmanager.dataSourceSettings);
+ const isReadOnly = isVanillaPrometheusAlertManagerDataSource(alertmanager.dataSourceSettings.name);
+
const detailHref = createUrl(DATASOURCES_ROUTES.Edit.replace(/:uid/gi, uid));
const handleEditConfiguration = () => onEditConfiguration(name);
diff --git a/public/app/features/alerting/unified/components/settings/__mocks__/api/datasources.json b/public/app/features/alerting/unified/components/settings/__mocks__/api/datasources.json
index a31e1fdc10e..e7ca54b8f86 100644
--- a/public/app/features/alerting/unified/components/settings/__mocks__/api/datasources.json
+++ b/public/app/features/alerting/unified/components/settings/__mocks__/api/datasources.json
@@ -19,6 +19,26 @@
},
"readOnly": false
},
+ {
+ "id": 183,
+ "uid": "xPVD2XISx",
+ "orgId": 1,
+ "name": "Provisioned Mimir-based Alertmanager",
+ "type": "alertmanager",
+ "typeName": "Alertmanager",
+ "typeLogoUrl": "public/app/plugins/datasource/prometheus/img/prometheus_logo.svg",
+ "access": "proxy",
+ "url": "http://foo.bar:9090/",
+ "user": "",
+ "database": "",
+ "basicAuth": false,
+ "isDefault": false,
+ "jsonData": {
+ "httpMethod": "POST",
+ "implementation": "mimir"
+ },
+ "readOnly": true
+ },
{
"id": 160,
"uid": "iETbvsT4z",
diff --git a/public/app/features/alerting/unified/components/settings/__mocks__/server.ts b/public/app/features/alerting/unified/components/settings/__mocks__/server.ts
index 0a64f290eac..428b6f54de6 100644
--- a/public/app/features/alerting/unified/components/settings/__mocks__/server.ts
+++ b/public/app/features/alerting/unified/components/settings/__mocks__/server.ts
@@ -23,7 +23,7 @@ export { vanillaAlertmanagerConfig as VanillaAlertmanagerConfiguration };
export { history as alertmanagerConfigurationHistory };
export const EXTERNAL_VANILLA_ALERTMANAGER_UID = 'vanilla-alertmanager';
-export const PROVISIONED_VANILLA_ALERTMANAGER_UID = 'provisioned-alertmanager';
+export const PROVISIONED_MIMIR_ALERTMANAGER_UID = 'provisioned-alertmanager';
jest.spyOn(config, 'getAllDataSources');
@@ -40,9 +40,9 @@ const mockDataSources = {
implementation: AlertManagerImplementation.prometheus,
},
}),
- [PROVISIONED_VANILLA_ALERTMANAGER_UID]: mockDataSource({
- uid: PROVISIONED_VANILLA_ALERTMANAGER_UID,
- name: PROVISIONED_VANILLA_ALERTMANAGER_UID,
+ [PROVISIONED_MIMIR_ALERTMANAGER_UID]: mockDataSource({
+ uid: PROVISIONED_MIMIR_ALERTMANAGER_UID,
+ name: PROVISIONED_MIMIR_ALERTMANAGER_UID,
type: DataSourceType.Alertmanager,
jsonData: {
// this is a mutable data source type but we're making it readOnly
@@ -70,7 +70,7 @@ export function setupVanillaAlertmanagerServer(server: SetupServerApi) {
server.use(
createVanillaAlertmanagerConfigurationHandler(EXTERNAL_VANILLA_ALERTMANAGER_UID),
- ...createAlertmanagerConfigurationHandlers(PROVISIONED_VANILLA_ALERTMANAGER_UID)
+ ...createAlertmanagerConfigurationHandlers(PROVISIONED_MIMIR_ALERTMANAGER_UID)
);
return server;
diff --git a/public/app/features/alerting/unified/utils/datasource.ts b/public/app/features/alerting/unified/utils/datasource.ts
index bb5fb463c8d..4a74e122e2e 100644
--- a/public/app/features/alerting/unified/utils/datasource.ts
+++ b/public/app/features/alerting/unified/utils/datasource.ts
@@ -210,8 +210,8 @@ export function isVanillaPrometheusAlertManagerDataSource(name: string): boolean
);
}
-export function isProvisionedDataSource(name: string): boolean {
- return getAlertmanagerDataSourceByName(name)?.readOnly === true;
+export function isProvisionedDataSource(dataSource: DataSourceSettings): boolean {
+ return dataSource.readOnly === true;
}
export function isGrafanaRulesSource(