mirror of
https://github.com/prymitive/karma
synced 2026-08-23 11:56:20 +00:00
fix(ui): only show one silence per Alertmanager cluster
HA clusters share silences which means that they are currently duplicated for each alertmanager instance in that cluster
This commit is contained in:
@@ -45,18 +45,35 @@ const Alert = observer(
|
||||
BorderClassMap[alert.state] || "border-warning"
|
||||
];
|
||||
|
||||
let silences = {};
|
||||
for (let am of alert.alertmanager) {
|
||||
if (!silences[am.cluster]) {
|
||||
silences[am.cluster] = {
|
||||
alertmanager: am,
|
||||
silences: []
|
||||
};
|
||||
}
|
||||
for (let silenceID of am.silencedBy) {
|
||||
if (!silences[am.cluster].silences.includes(silenceID)) {
|
||||
silences[am.cluster].silences.push(silenceID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<li className={classNames.join(" ")}>
|
||||
<div>
|
||||
{alert.annotations.filter(a => a.isLink === false).map(a => (
|
||||
<RenderNonLinkAnnotation
|
||||
key={a.name}
|
||||
name={a.name}
|
||||
value={a.value}
|
||||
visible={a.visible}
|
||||
afterUpdate={afterUpdate}
|
||||
/>
|
||||
))}
|
||||
{alert.annotations
|
||||
.filter(a => a.isLink === false)
|
||||
.map(a => (
|
||||
<RenderNonLinkAnnotation
|
||||
key={a.name}
|
||||
name={a.name}
|
||||
value={a.value}
|
||||
visible={a.visible}
|
||||
afterUpdate={afterUpdate}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<AlertMenu
|
||||
group={group}
|
||||
@@ -81,15 +98,21 @@ const Alert = observer(
|
||||
value={alert.receiver}
|
||||
/>
|
||||
) : null}
|
||||
{alert.annotations.filter(a => a.isLink === true).map(a => (
|
||||
<RenderLinkAnnotation key={a.name} name={a.name} value={a.value} />
|
||||
))}
|
||||
{alert.alertmanager.map(am =>
|
||||
am.silencedBy.map(silenceID => (
|
||||
{alert.annotations
|
||||
.filter(a => a.isLink === true)
|
||||
.map(a => (
|
||||
<RenderLinkAnnotation
|
||||
key={a.name}
|
||||
name={a.name}
|
||||
value={a.value}
|
||||
/>
|
||||
))}
|
||||
{Object.values(silences).map(clusterSilences =>
|
||||
clusterSilences.silences.map(silenceID => (
|
||||
<Silence
|
||||
key={silenceID}
|
||||
silenceFormStore={silenceFormStore}
|
||||
alertmanagerState={am}
|
||||
alertmanagerState={clusterSilences.alertmanager}
|
||||
silenceID={silenceID}
|
||||
afterUpdate={afterUpdate}
|
||||
/>
|
||||
|
||||
@@ -96,6 +96,35 @@ describe("<Alert />", () => {
|
||||
expect(silence.html()).toMatch(/silence123456789/);
|
||||
});
|
||||
|
||||
it("renders only one silence for HA cluster", () => {
|
||||
const alert = MockedAlert();
|
||||
alert.alertmanager = [
|
||||
{
|
||||
name: "am1",
|
||||
cluster: "ha",
|
||||
state: "suppressed",
|
||||
startsAt: "2018-08-14T17:36:40.017867056Z",
|
||||
endsAt: "0001-01-01T00:00:00Z",
|
||||
source: "localhost/am1",
|
||||
silencedBy: ["silence123456789"]
|
||||
},
|
||||
{
|
||||
name: "am2",
|
||||
cluster: "ha",
|
||||
state: "suppressed",
|
||||
startsAt: "2018-08-14T17:36:40.017867056Z",
|
||||
endsAt: "0001-01-01T00:00:00Z",
|
||||
source: "localhost/am2",
|
||||
silencedBy: ["silence123456789"]
|
||||
}
|
||||
];
|
||||
const group = MockAlertGroup({}, [alert], [], {});
|
||||
const tree = MountedAlert(alert, group, false, false);
|
||||
const silence = tree.find("Silence");
|
||||
expect(silence).toHaveLength(1);
|
||||
expect(silence.html()).toMatch(/silence123456789/);
|
||||
});
|
||||
|
||||
it("uses BorderClassMap.active when @state=active", () => {
|
||||
const alert = MockedAlert();
|
||||
alert.state = "active";
|
||||
|
||||
@@ -249,7 +249,7 @@ const Silence = inject("alertStore")(
|
||||
// and we need to lookup the actual silence data in the store.
|
||||
// Data might be missing from the store so first check if we have
|
||||
// anything for this alertmanager instance
|
||||
const amSilences = alertStore.data.silences[alertmanagerState.name];
|
||||
const amSilences = alertStore.data.silences[alertmanagerState.cluster];
|
||||
if (!amSilences) return null;
|
||||
|
||||
// next check if alertmanager has our silence ID
|
||||
|
||||
@@ -17,6 +17,7 @@ const mockAfterUpdate = jest.fn();
|
||||
|
||||
const alertmanager = {
|
||||
name: "default",
|
||||
cluster: "default",
|
||||
state: "suppressed",
|
||||
startsAt: "2000-01-01T10:00:00Z",
|
||||
endsAt: "0001-01-01T00:00:00Z",
|
||||
|
||||
@@ -11,6 +11,7 @@ const Annotation = PropTypes.exact({
|
||||
|
||||
const APIAlertAlertmanagerState = PropTypes.exact({
|
||||
name: PropTypes.string.isRequired,
|
||||
cluster: PropTypes.string.isRequired,
|
||||
state: AlertState.isRequired,
|
||||
startsAt: PropTypes.string.isRequired,
|
||||
endsAt: PropTypes.string.isRequired,
|
||||
|
||||
@@ -14,6 +14,7 @@ const MockAlert = (annotations, labels, state) => ({
|
||||
alertmanager: [
|
||||
{
|
||||
name: "default",
|
||||
cluster: "default",
|
||||
state: "active",
|
||||
startsAt: "2018-08-14T17:36:40.017867056Z",
|
||||
endsAt: "0001-01-01T00:00:00Z",
|
||||
|
||||
Reference in New Issue
Block a user