mirror of https://github.com/grafana/grafana
Alerting: Configure alert manager data source as an external AM (#52081)
Co-authored-by: Jean-Philippe Quéméner <JohnnyQQQQ@users.noreply.github.com> Co-authored-by: gotjosh <josue.abreu@gmail.com> Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com>pull/53024/head
parent
1fc9f6f1c6
commit
54f2c056f5
@ -0,0 +1,122 @@ |
||||
import { css } from '@emotion/css'; |
||||
import { capitalize } from 'lodash'; |
||||
import React from 'react'; |
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data'; |
||||
import { Badge, CallToActionCard, Card, Icon, LinkButton, Tooltip, useStyles2 } from '@grafana/ui'; |
||||
|
||||
import { ExternalDataSourceAM } from '../../hooks/useExternalAmSelector'; |
||||
import { makeDataSourceLink } from '../../utils/misc'; |
||||
|
||||
export interface ExternalAlertManagerDataSourcesProps { |
||||
alertmanagers: ExternalDataSourceAM[]; |
||||
inactive: boolean; |
||||
} |
||||
|
||||
export function ExternalAlertmanagerDataSources({ alertmanagers, inactive }: ExternalAlertManagerDataSourcesProps) { |
||||
const styles = useStyles2(getStyles); |
||||
|
||||
return ( |
||||
<> |
||||
<h5>Alertmanagers data sources</h5> |
||||
<div className={styles.muted}> |
||||
Alertmanager data sources support a configuration setting that allows you to choose to send Grafana-managed |
||||
alerts to that Alertmanager. <br /> |
||||
Below, you can see the list of all Alertmanager data sources that have this setting enabled. |
||||
</div> |
||||
{alertmanagers.length === 0 && ( |
||||
<CallToActionCard |
||||
message={ |
||||
<div> |
||||
There are no Alertmanager data sources configured to receive Grafana-managed alerts. <br /> |
||||
You can change this by selecting Receive Grafana Alerts in a data source configuration. |
||||
</div> |
||||
} |
||||
callToActionElement={<LinkButton href="/datasources">Go to data sources</LinkButton>} |
||||
className={styles.externalDsCTA} |
||||
/> |
||||
)} |
||||
{alertmanagers.length > 0 && ( |
||||
<div className={styles.externalDs}> |
||||
{alertmanagers.map((am) => ( |
||||
<ExternalAMdataSourceCard key={am.dataSource.uid} alertmanager={am} inactive={inactive} /> |
||||
))} |
||||
</div> |
||||
)} |
||||
</> |
||||
); |
||||
} |
||||
|
||||
interface ExternalAMdataSourceCardProps { |
||||
alertmanager: ExternalDataSourceAM; |
||||
inactive: boolean; |
||||
} |
||||
|
||||
export function ExternalAMdataSourceCard({ alertmanager, inactive }: ExternalAMdataSourceCardProps) { |
||||
const styles = useStyles2(getStyles); |
||||
|
||||
const { dataSource, status, statusInconclusive, url } = alertmanager; |
||||
|
||||
return ( |
||||
<Card> |
||||
<Card.Heading className={styles.externalHeading}> |
||||
{dataSource.name}{' '} |
||||
{statusInconclusive && ( |
||||
<Tooltip content="Multiple Alertmangers have the same URL configured. The state might be inconclusive."> |
||||
<Icon name="exclamation-triangle" size="md" className={styles.externalWarningIcon} /> |
||||
</Tooltip> |
||||
)} |
||||
</Card.Heading> |
||||
<Card.Figure> |
||||
<img |
||||
src="public/app/plugins/datasource/alertmanager/img/logo.svg" |
||||
alt="" |
||||
height="40px" |
||||
width="40px" |
||||
style={{ objectFit: 'contain' }} |
||||
/> |
||||
</Card.Figure> |
||||
<Card.Tags> |
||||
{inactive ? ( |
||||
<Badge |
||||
text="Inactive" |
||||
color="red" |
||||
tooltip="Grafana is configured to send alerts to the built-in internal Alertmanager only. External Alertmanagers do not receive any alerts." |
||||
/> |
||||
) : ( |
||||
<Badge |
||||
text={capitalize(status)} |
||||
color={status === 'dropped' ? 'red' : status === 'active' ? 'green' : 'orange'} |
||||
/> |
||||
)} |
||||
</Card.Tags> |
||||
<Card.Meta>{url}</Card.Meta> |
||||
<Card.Actions> |
||||
<LinkButton href={makeDataSourceLink(dataSource)} size="sm" variant="secondary"> |
||||
Go to datasouce |
||||
</LinkButton> |
||||
</Card.Actions> |
||||
</Card> |
||||
); |
||||
} |
||||
|
||||
export const getStyles = (theme: GrafanaTheme2) => ({ |
||||
muted: css` |
||||
color: ${theme.colors.text.secondary}; |
||||
`,
|
||||
externalHeading: css` |
||||
justify-content: flex-start; |
||||
`,
|
||||
externalWarningIcon: css` |
||||
margin: ${theme.spacing(0, 1)}; |
||||
fill: ${theme.colors.warning.main}; |
||||
`,
|
||||
externalDs: css` |
||||
display: grid; |
||||
gap: ${theme.spacing(1)}; |
||||
padding: ${theme.spacing(2, 0)}; |
||||
`,
|
||||
externalDsCTA: css` |
||||
margin: ${theme.spacing(2, 0)}; |
||||
`,
|
||||
}); |
@ -1,167 +0,0 @@ |
||||
import * as reactRedux from 'react-redux'; |
||||
|
||||
import { useExternalAmSelector } from './useExternalAmSelector'; |
||||
|
||||
const createMockStoreState = ( |
||||
activeAlertmanagers: Array<{ url: string }>, |
||||
droppedAlertmanagers: Array<{ url: string }>, |
||||
alertmanagerConfig: string[] |
||||
) => ({ |
||||
unifiedAlerting: { |
||||
externalAlertmanagers: { |
||||
discoveredAlertmanagers: { |
||||
result: { |
||||
data: { |
||||
activeAlertManagers: activeAlertmanagers, |
||||
droppedAlertManagers: droppedAlertmanagers, |
||||
}, |
||||
}, |
||||
}, |
||||
alertmanagerConfig: { |
||||
result: { |
||||
alertmanagers: alertmanagerConfig, |
||||
}, |
||||
}, |
||||
}, |
||||
}, |
||||
}); |
||||
|
||||
describe('useExternalAmSelector', () => { |
||||
const useSelectorMock = jest.spyOn(reactRedux, 'useSelector'); |
||||
beforeEach(() => { |
||||
useSelectorMock.mockClear(); |
||||
}); |
||||
it('should have one in pending', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback(createMockStoreState([], [], ['some/url/to/am'])); |
||||
}); |
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'some/url/to/am', |
||||
status: 'pending', |
||||
actualUrl: '', |
||||
}, |
||||
]); |
||||
}); |
||||
|
||||
it('should have one active, one pending', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback( |
||||
createMockStoreState([{ url: 'some/url/to/am/api/v2/alerts' }], [], ['some/url/to/am', 'some/url/to/am1']) |
||||
); |
||||
}); |
||||
|
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'some/url/to/am', |
||||
actualUrl: 'some/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'some/url/to/am1', |
||||
actualUrl: '', |
||||
status: 'pending', |
||||
}, |
||||
]); |
||||
}); |
||||
|
||||
it('should have two active', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback( |
||||
createMockStoreState( |
||||
[{ url: 'some/url/to/am/api/v2/alerts' }, { url: 'some/url/to/am1/api/v2/alerts' }], |
||||
[], |
||||
['some/url/to/am', 'some/url/to/am1'] |
||||
) |
||||
); |
||||
}); |
||||
|
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'some/url/to/am', |
||||
actualUrl: 'some/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'some/url/to/am1', |
||||
actualUrl: 'some/url/to/am1/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
]); |
||||
}); |
||||
|
||||
it('should have one active, one dropped, one pending', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback( |
||||
createMockStoreState( |
||||
[{ url: 'some/url/to/am/api/v2/alerts' }], |
||||
[{ url: 'some/dropped/url/api/v2/alerts' }], |
||||
['some/url/to/am', 'some/url/to/am1'] |
||||
) |
||||
); |
||||
}); |
||||
|
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'some/url/to/am', |
||||
actualUrl: 'some/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'some/url/to/am1', |
||||
actualUrl: '', |
||||
status: 'pending', |
||||
}, |
||||
{ |
||||
url: 'some/dropped/url', |
||||
actualUrl: 'some/dropped/url/api/v2/alerts', |
||||
status: 'dropped', |
||||
}, |
||||
]); |
||||
}); |
||||
|
||||
it('The number of alert managers should match config entries when there are multiple entries of the same url', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback( |
||||
createMockStoreState( |
||||
[ |
||||
{ url: 'same/url/to/am/api/v2/alerts' }, |
||||
{ url: 'same/url/to/am/api/v2/alerts' }, |
||||
{ url: 'same/url/to/am/api/v2/alerts' }, |
||||
], |
||||
[], |
||||
['same/url/to/am', 'same/url/to/am', 'same/url/to/am'] |
||||
) |
||||
); |
||||
}); |
||||
|
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers.length).toBe(3); |
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'same/url/to/am', |
||||
actualUrl: 'same/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'same/url/to/am', |
||||
actualUrl: 'same/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'same/url/to/am', |
||||
actualUrl: 'same/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
]); |
||||
}); |
||||
}); |
@ -0,0 +1,416 @@ |
||||
import { renderHook } from '@testing-library/react-hooks'; |
||||
import React from 'react'; |
||||
import * as reactRedux from 'react-redux'; |
||||
|
||||
import { DataSourceJsonData, DataSourceSettings } from '@grafana/data'; |
||||
import { config } from '@grafana/runtime'; |
||||
import { AlertmanagerChoice, AlertManagerDataSourceJsonData } from 'app/plugins/datasource/alertmanager/types'; |
||||
|
||||
import { mockDataSource, mockDataSourcesStore, mockStore } from '../mocks'; |
||||
|
||||
import { useExternalAmSelector, useExternalDataSourceAlertmanagers } from './useExternalAmSelector'; |
||||
|
||||
const useSelectorMock = jest.spyOn(reactRedux, 'useSelector'); |
||||
|
||||
describe('useExternalAmSelector', () => { |
||||
beforeEach(() => { |
||||
useSelectorMock.mockClear(); |
||||
}); |
||||
it('should have one in pending', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback(createMockStoreState([], [], ['some/url/to/am'])); |
||||
}); |
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'some/url/to/am', |
||||
status: 'pending', |
||||
actualUrl: '', |
||||
}, |
||||
]); |
||||
}); |
||||
|
||||
it('should have one active, one pending', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback( |
||||
createMockStoreState([{ url: 'some/url/to/am/api/v2/alerts' }], [], ['some/url/to/am', 'some/url/to/am1']) |
||||
); |
||||
}); |
||||
|
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'some/url/to/am', |
||||
actualUrl: 'some/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'some/url/to/am1', |
||||
actualUrl: '', |
||||
status: 'pending', |
||||
}, |
||||
]); |
||||
}); |
||||
|
||||
it('should have two active', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback( |
||||
createMockStoreState( |
||||
[{ url: 'some/url/to/am/api/v2/alerts' }, { url: 'some/url/to/am1/api/v2/alerts' }], |
||||
[], |
||||
['some/url/to/am', 'some/url/to/am1'] |
||||
) |
||||
); |
||||
}); |
||||
|
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'some/url/to/am', |
||||
actualUrl: 'some/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'some/url/to/am1', |
||||
actualUrl: 'some/url/to/am1/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
]); |
||||
}); |
||||
|
||||
it('should have one active, one dropped, one pending', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback( |
||||
createMockStoreState( |
||||
[{ url: 'some/url/to/am/api/v2/alerts' }], |
||||
[{ url: 'some/dropped/url/api/v2/alerts' }], |
||||
['some/url/to/am', 'some/url/to/am1'] |
||||
) |
||||
); |
||||
}); |
||||
|
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'some/url/to/am', |
||||
actualUrl: 'some/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'some/url/to/am1', |
||||
actualUrl: '', |
||||
status: 'pending', |
||||
}, |
||||
{ |
||||
url: 'some/dropped/url', |
||||
actualUrl: 'some/dropped/url/api/v2/alerts', |
||||
status: 'dropped', |
||||
}, |
||||
]); |
||||
}); |
||||
|
||||
it('The number of alert managers should match config entries when there are multiple entries of the same url', () => { |
||||
useSelectorMock.mockImplementation((callback) => { |
||||
return callback( |
||||
createMockStoreState( |
||||
[ |
||||
{ url: 'same/url/to/am/api/v2/alerts' }, |
||||
{ url: 'same/url/to/am/api/v2/alerts' }, |
||||
{ url: 'same/url/to/am/api/v2/alerts' }, |
||||
], |
||||
[], |
||||
['same/url/to/am', 'same/url/to/am', 'same/url/to/am'] |
||||
) |
||||
); |
||||
}); |
||||
|
||||
const alertmanagers = useExternalAmSelector(); |
||||
|
||||
expect(alertmanagers.length).toBe(3); |
||||
expect(alertmanagers).toEqual([ |
||||
{ |
||||
url: 'same/url/to/am', |
||||
actualUrl: 'same/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'same/url/to/am', |
||||
actualUrl: 'same/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
{ |
||||
url: 'same/url/to/am', |
||||
actualUrl: 'same/url/to/am/api/v2/alerts', |
||||
status: 'active', |
||||
}, |
||||
]); |
||||
}); |
||||
}); |
||||
|
||||
describe('useExternalDataSourceAlertmanagers', () => { |
||||
beforeEach(() => { |
||||
useSelectorMock.mockRestore(); |
||||
}); |
||||
|
||||
it('Should merge data sources information from config and api responses', () => { |
||||
// Arrange
|
||||
const { dsSettings, dsInstanceSettings } = setupAlertmanagerDataSource({ url: 'http://grafana.com' }); |
||||
|
||||
config.datasources = { |
||||
'External Alertmanager': dsInstanceSettings, |
||||
}; |
||||
|
||||
const store = mockDataSourcesStore({ |
||||
dataSources: [dsSettings], |
||||
}); |
||||
|
||||
const wrapper: React.FC = ({ children }) => <reactRedux.Provider store={store}>{children}</reactRedux.Provider>; |
||||
|
||||
// Act
|
||||
const { |
||||
result: { current }, |
||||
} = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper }); |
||||
|
||||
// Assert
|
||||
expect(current).toHaveLength(1); |
||||
expect(current[0].dataSource.uid).toBe('1'); |
||||
expect(current[0].url).toBe('http://grafana.com'); |
||||
}); |
||||
|
||||
it('Should have active state if available in the activeAlertManagers', () => { |
||||
// Arrange
|
||||
const { dsSettings, dsInstanceSettings } = setupAlertmanagerDataSource({ url: 'http://grafana.com' }); |
||||
|
||||
config.datasources = { |
||||
'External Alertmanager': dsInstanceSettings, |
||||
}; |
||||
|
||||
const store = mockStore((state) => { |
||||
state.dataSources.dataSources = [dsSettings]; |
||||
state.unifiedAlerting.externalAlertmanagers.discoveredAlertmanagers.result = { |
||||
data: { |
||||
activeAlertManagers: [{ url: 'http://grafana.com/api/v2/alerts' }], |
||||
droppedAlertManagers: [], |
||||
}, |
||||
}; |
||||
}); |
||||
|
||||
const wrapper: React.FC = ({ children }) => <reactRedux.Provider store={store}>{children}</reactRedux.Provider>; |
||||
|
||||
// Act
|
||||
const { |
||||
result: { current }, |
||||
} = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper }); |
||||
|
||||
// Assert
|
||||
expect(current).toHaveLength(1); |
||||
expect(current[0].status).toBe('active'); |
||||
expect(current[0].statusInconclusive).toBe(false); |
||||
}); |
||||
|
||||
it('Should have dropped state if available in the droppedAlertManagers', () => { |
||||
// Arrange
|
||||
const { dsSettings, dsInstanceSettings } = setupAlertmanagerDataSource({ url: 'http://grafana.com' }); |
||||
|
||||
config.datasources = { |
||||
'External Alertmanager': dsInstanceSettings, |
||||
}; |
||||
|
||||
const store = mockStore((state) => { |
||||
state.dataSources.dataSources = [dsSettings]; |
||||
state.unifiedAlerting.externalAlertmanagers.discoveredAlertmanagers.result = { |
||||
data: { |
||||
activeAlertManagers: [], |
||||
droppedAlertManagers: [{ url: 'http://grafana.com/api/v2/alerts' }], |
||||
}, |
||||
}; |
||||
}); |
||||
|
||||
const wrapper: React.FC = ({ children }) => <reactRedux.Provider store={store}>{children}</reactRedux.Provider>; |
||||
|
||||
// Act
|
||||
const { |
||||
result: { current }, |
||||
} = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper }); |
||||
|
||||
// Assert
|
||||
expect(current).toHaveLength(1); |
||||
expect(current[0].status).toBe('dropped'); |
||||
expect(current[0].statusInconclusive).toBe(false); |
||||
}); |
||||
|
||||
it('Should have pending state if not available neither in dropped nor in active alertManagers', () => { |
||||
// Arrange
|
||||
const { dsSettings, dsInstanceSettings } = setupAlertmanagerDataSource(); |
||||
|
||||
config.datasources = { |
||||
'External Alertmanager': dsInstanceSettings, |
||||
}; |
||||
|
||||
const store = mockStore((state) => { |
||||
state.dataSources.dataSources = [dsSettings]; |
||||
state.unifiedAlerting.externalAlertmanagers.discoveredAlertmanagers.result = { |
||||
data: { |
||||
activeAlertManagers: [], |
||||
droppedAlertManagers: [], |
||||
}, |
||||
}; |
||||
}); |
||||
|
||||
const wrapper: React.FC = ({ children }) => <reactRedux.Provider store={store}>{children}</reactRedux.Provider>; |
||||
|
||||
// Act
|
||||
const { |
||||
result: { current }, |
||||
} = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper }); |
||||
|
||||
// Assert
|
||||
expect(current).toHaveLength(1); |
||||
expect(current[0].status).toBe('pending'); |
||||
expect(current[0].statusInconclusive).toBe(false); |
||||
}); |
||||
|
||||
it('Should match Alertmanager url when datasource url does not have protocol specified', () => { |
||||
// Arrange
|
||||
const { dsSettings, dsInstanceSettings } = setupAlertmanagerDataSource({ url: 'localhost:9093' }); |
||||
|
||||
config.datasources = { |
||||
'External Alertmanager': dsInstanceSettings, |
||||
}; |
||||
|
||||
const store = mockStore((state) => { |
||||
state.dataSources.dataSources = [dsSettings]; |
||||
state.unifiedAlerting.externalAlertmanagers.discoveredAlertmanagers.result = { |
||||
data: { |
||||
activeAlertManagers: [{ url: 'http://localhost:9093/api/v2/alerts' }], |
||||
droppedAlertManagers: [], |
||||
}, |
||||
}; |
||||
}); |
||||
|
||||
const wrapper: React.FC = ({ children }) => <reactRedux.Provider store={store}>{children}</reactRedux.Provider>; |
||||
|
||||
// Act
|
||||
const { |
||||
result: { current }, |
||||
} = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper }); |
||||
|
||||
// Assert
|
||||
expect(current).toHaveLength(1); |
||||
expect(current[0].status).toBe('active'); |
||||
expect(current[0].url).toBe('localhost:9093'); |
||||
}); |
||||
|
||||
it('Should have inconclusive state when there are many Alertmanagers of the same URL', () => { |
||||
// Arrange
|
||||
const { dsSettings, dsInstanceSettings } = setupAlertmanagerDataSource({ url: 'http://grafana.com' }); |
||||
|
||||
config.datasources = { |
||||
'External Alertmanager': dsInstanceSettings, |
||||
}; |
||||
|
||||
const store = mockStore((state) => { |
||||
state.dataSources.dataSources = [dsSettings]; |
||||
state.unifiedAlerting.externalAlertmanagers.discoveredAlertmanagers.result = { |
||||
data: { |
||||
activeAlertManagers: [ |
||||
{ url: 'http://grafana.com/api/v2/alerts' }, |
||||
{ url: 'http://grafana.com/api/v2/alerts' }, |
||||
], |
||||
droppedAlertManagers: [], |
||||
}, |
||||
}; |
||||
}); |
||||
|
||||
const wrapper: React.FC = ({ children }) => <reactRedux.Provider store={store}>{children}</reactRedux.Provider>; |
||||
|
||||
// Act
|
||||
const { |
||||
result: { current }, |
||||
} = renderHook(() => useExternalDataSourceAlertmanagers(), { wrapper }); |
||||
|
||||
// Assert
|
||||
expect(current).toHaveLength(1); |
||||
expect(current[0].status).toBe('active'); |
||||
expect(current[0].statusInconclusive).toBe(true); |
||||
}); |
||||
}); |
||||
|
||||
function setupAlertmanagerDataSource(partialDsSettings?: Partial<DataSourceSettings<AlertManagerDataSourceJsonData>>) { |
||||
const dsCommonConfig = { |
||||
uid: '1', |
||||
name: 'External Alertmanager', |
||||
type: 'alertmanager', |
||||
jsonData: { handleGrafanaManagedAlerts: true } as AlertManagerDataSourceJsonData, |
||||
}; |
||||
|
||||
const dsInstanceSettings = mockDataSource(dsCommonConfig); |
||||
|
||||
const dsSettings = mockApiDataSource({ |
||||
...dsCommonConfig, |
||||
...partialDsSettings, |
||||
}); |
||||
|
||||
return { dsSettings, dsInstanceSettings }; |
||||
} |
||||
|
||||
function mockApiDataSource(partial: Partial<DataSourceSettings<DataSourceJsonData, {}>> = {}) { |
||||
const dsSettings: DataSourceSettings<DataSourceJsonData, {}> = { |
||||
uid: '1', |
||||
id: 1, |
||||
name: '', |
||||
url: '', |
||||
type: '', |
||||
access: '', |
||||
orgId: 1, |
||||
typeLogoUrl: '', |
||||
typeName: '', |
||||
user: '', |
||||
database: '', |
||||
basicAuth: false, |
||||
isDefault: false, |
||||
basicAuthUser: '', |
||||
jsonData: { handleGrafanaManagedAlerts: true } as AlertManagerDataSourceJsonData, |
||||
secureJsonFields: {}, |
||||
readOnly: false, |
||||
withCredentials: false, |
||||
...partial, |
||||
}; |
||||
|
||||
return dsSettings; |
||||
} |
||||
|
||||
const createMockStoreState = ( |
||||
activeAlertmanagers: Array<{ url: string }>, |
||||
droppedAlertmanagers: Array<{ url: string }>, |
||||
alertmanagerConfig: string[] |
||||
) => { |
||||
return { |
||||
unifiedAlerting: { |
||||
externalAlertmanagers: { |
||||
discoveredAlertmanagers: { |
||||
result: { |
||||
data: { |
||||
activeAlertManagers: activeAlertmanagers, |
||||
droppedAlertManagers: droppedAlertmanagers, |
||||
}, |
||||
}, |
||||
dispatched: false, |
||||
loading: false, |
||||
}, |
||||
alertmanagerConfig: { |
||||
result: { |
||||
alertmanagers: alertmanagerConfig, |
||||
alertmanagersChoice: AlertmanagerChoice.All, |
||||
}, |
||||
dispatched: false, |
||||
loading: false, |
||||
}, |
||||
}, |
||||
}, |
||||
}; |
||||
}; |
Loading…
Reference in new issue