-
Add new silence
+
+ {silenceFormStore.data.silenceID === null
+ ? "Add new silence"
+ : `Editing silence ${silenceFormStore.data.silenceID}`}
+
diff --git a/ui/src/Components/SilenceModal/SilenceModalContent.test.js b/ui/src/Components/SilenceModal/SilenceModalContent.test.js
index 0854e9842..0e9497637 100644
--- a/ui/src/Components/SilenceModal/SilenceModalContent.test.js
+++ b/ui/src/Components/SilenceModal/SilenceModalContent.test.js
@@ -44,4 +44,18 @@ describe("", () => {
const ctrl = tree.find("SilenceSubmitController");
expect(ctrl).toHaveLength(1);
});
+
+ it("title is 'Add new silence' when silenceFormStore.data.silenceID is null", () => {
+ silenceFormStore.data.silenceID = null;
+ const tree = ShallowSilenceModalContent();
+ const title = tree.find(".modal-title");
+ expect(title.text()).toBe("Add new silence");
+ });
+
+ it("title is 'Editing silence 12345' when silenceFormStore.data.silenceID is '12345'", () => {
+ silenceFormStore.data.silenceID = "12345";
+ const tree = ShallowSilenceModalContent();
+ const title = tree.find(".modal-title");
+ expect(title.text()).toBe("Editing silence 12345");
+ });
});
diff --git a/ui/src/Stores/SilenceFormStore.js b/ui/src/Stores/SilenceFormStore.js
index e8f993619..54f939c14 100644
--- a/ui/src/Stores/SilenceFormStore.js
+++ b/ui/src/Stores/SilenceFormStore.js
@@ -45,6 +45,7 @@ class SilenceFormStore {
{
inProgress: false,
wasValidated: false,
+ silenceID: null,
alertmanagers: [],
matchers: [],
startsAt: moment(),
@@ -79,6 +80,10 @@ class SilenceFormStore {
this.wasValidated = false;
},
+ resetSilenceID() {
+ this.silenceID = null;
+ },
+
// append a new empty matcher to the list
addEmptyMatcher() {
let m = NewEmptyMatcher();
@@ -135,6 +140,31 @@ class SilenceFormStore {
this.matchers = matchers;
},
+ fillFormFromSilence(alertmanager, silence) {
+ this.silenceID = silence.id;
+ this.alertmanagers = [
+ {
+ label: alertmanager.name,
+ value: alertmanager.publicURI
+ }
+ ];
+
+ const matchers = [];
+ for (const m of silence.matchers) {
+ const matcher = NewEmptyMatcher();
+ matcher.name = m.name;
+ matcher.values = [MatcherValueToObject(m.value)];
+ matcher.isRegex = m.isRegex;
+ matchers.push(matcher);
+ }
+ this.matchers = matchers;
+
+ this.startsAt = moment(silence.startsAt);
+ this.endsAt = moment(silence.endsAt);
+ this.comment = silence.comment;
+ this.author = silence.createdBy;
+ },
+
verifyStarEnd() {
const now = moment().second(0);
if (this.startsAt.isBefore(now)) {
@@ -186,8 +216,12 @@ class SilenceFormStore {
createdBy: this.author,
comment: this.comment
};
+ if (this.silenceID !== null) {
+ payload.id = this.silenceID;
+ }
return payload;
},
+
get toDuration() {
const data = {
days: this.endsAt.diff(this.startsAt, "days"),
@@ -200,9 +234,11 @@ class SilenceFormStore {
{
resetStartEnd: action.bound,
resetProgress: action.bound,
+ resetSilenceID: action.bound,
addEmptyMatcher: action.bound,
deleteMatcher: action.bound,
fillMatchersFromGroup: action.bound,
+ fillFormFromSilence: action.bound,
verifyStarEnd: action.bound,
incStart: action.bound,
decStart: action.bound,
diff --git a/ui/src/Stores/SilenceFormStore.test.js b/ui/src/Stores/SilenceFormStore.test.js
index fab7d93b0..6c85ccfca 100644
--- a/ui/src/Stores/SilenceFormStore.test.js
+++ b/ui/src/Stores/SilenceFormStore.test.js
@@ -1,6 +1,11 @@
import moment from "moment";
-import { MockAlert, MockAlertGroup } from "__mocks__/Alerts.js";
+import {
+ MockAlert,
+ MockAlertGroup,
+ MockSilence,
+ MockAlertmanager
+} from "__mocks__/Alerts.js";
import { SilenceFormStore, NewEmptyMatcher } from "./SilenceFormStore";
let store;
@@ -8,6 +13,30 @@ beforeEach(() => {
store = new SilenceFormStore();
});
+const MockGroup = () => {
+ const alerts = [
+ MockAlert([], { instance: "prod1", cluster: "prod" }),
+ MockAlert([], { instance: "prod2", cluster: "prod" }),
+ MockAlert([], { instance: "dev1", cluster: "dev" })
+ ];
+ const group = MockAlertGroup({ alertname: "FakeAlert" }, alerts, [], {
+ job: "mock"
+ });
+ return group;
+};
+
+const MockAlertmanagerOption = () => ({
+ label: "default",
+ value: "http://localhost"
+});
+
+const MockMatcher = (name, values) => {
+ const matcher = NewEmptyMatcher();
+ matcher.name = name;
+ matcher.values = values;
+ return matcher;
+};
+
describe("SilenceFormStore.toggle", () => {
it("toggle() toggles 'visible' correctly", () => {
expect(store.toggle.visible).toBe(false);
@@ -32,18 +61,6 @@ describe("SilenceFormStore.toggle", () => {
});
});
-const MockGroup = () => {
- const alerts = [
- MockAlert([], { instance: "prod1", cluster: "prod" }),
- MockAlert([], { instance: "prod2", cluster: "prod" }),
- MockAlert([], { instance: "dev1", cluster: "dev" })
- ];
- const group = MockAlertGroup({ alertname: "FakeAlert" }, alerts, [], {
- job: "mock"
- });
- return group;
-};
-
describe("SilenceFormStore.data", () => {
it("resetStartEnd() sets startsAt and endsAt to defaults", () => {
store.data.startsAt = moment([2000, 1, 1, 0, 1, 0]);
@@ -167,6 +184,63 @@ describe("SilenceFormStore.data", () => {
);
});
+ it("fillFormFromSilence() sets silenceID", () => {
+ const alertmanager = MockAlertmanager();
+ const silence = MockSilence();
+ store.data.fillFormFromSilence(alertmanager, silence);
+ expect(store.data.silenceID).toBe(silence.id);
+ });
+
+ it("fillFormFromSilence() creates payload that matches silence data", () => {
+ const alertmanager = MockAlertmanager();
+ const silence = MockSilence();
+ store.data.fillFormFromSilence(alertmanager, silence);
+
+ expect(store.data.alertmanagers).toHaveLength(1);
+ expect(store.data.alertmanagers[0]).toMatchObject({
+ label: alertmanager.name,
+ value: alertmanager.publicURI
+ });
+
+ expect(store.data.matchers).toHaveLength(2);
+ expect(store.data.matchers).toContainEqual(
+ expect.objectContaining({
+ name: "foo",
+ values: [{ label: "bar", value: "bar" }],
+ isRegex: false
+ })
+ );
+ expect(store.data.matchers).toContainEqual(
+ expect.objectContaining({
+ name: "baz",
+ values: [{ label: "regex", value: "regex" }],
+ isRegex: true
+ })
+ );
+
+ expect(store.data.startsAt.toISOString()).toBe(
+ moment([2000, 0, 1, 0, 0, 0]).toISOString()
+ );
+ expect(store.data.endsAt.toISOString()).toBe(
+ moment([2000, 0, 1, 1, 0, 0]).toISOString()
+ );
+
+ expect(store.data.author).toBe("me@example.com");
+ expect(store.data.comment).toBe("Mocked Silence");
+ });
+
+ it("toAlertmanagerPayload constains id when store.data.silenceID is set", () => {
+ store.data.silenceID = "12345";
+ expect(store.data.toAlertmanagerPayload).toMatchObject({
+ id: "12345"
+ });
+ });
+
+ it("toAlertmanagerPayload doesn't contain id when store.data.silenceID is null", () => {
+ store.data.silenceID = null;
+ expect(store.data.toAlertmanagerPayload.id).toBeUndefined();
+ });
+
it("toAlertmanagerPayload creates payload that matches snapshot", () => {
const group = MockGroup();
store.data.fillMatchersFromGroup(group);
@@ -174,24 +248,12 @@ describe("SilenceFormStore.data", () => {
store.data.addEmptyMatcher();
store.data.startsAt = moment([2000, 1, 1, 0, 0, 0]);
store.data.endsAt = moment([2000, 1, 1, 1, 0, 0]);
- store.data.createdBy = "me@example.com";
+ store.data.author = "me@example.com";
store.data.comment = "toAlertmanagerPayload test";
expect(store.data.toAlertmanagerPayload).toMatchSnapshot();
});
});
-const MockAlertmanager = () => ({
- label: "default",
- value: "http://localhost"
-});
-
-const MockMatcher = (name, values) => {
- const matcher = NewEmptyMatcher();
- matcher.name = name;
- matcher.values = values;
- return matcher;
-};
-
describe("SilenceFormStore.data.isValid", () => {
it("isValid returns 'false' if alertmanagers list is empty", () => {
store.data.matchers = [MockMatcher("foo", ["bar"])];
@@ -201,7 +263,7 @@ describe("SilenceFormStore.data.isValid", () => {
});
it("isValid returns 'false' if matchers list is empty", () => {
- store.data.alertmanagers = [MockAlertmanager];
+ store.data.alertmanagers = [MockAlertmanagerOption];
store.data.matchers = [];
store.data.author = "me@example.com";
store.data.comment = "fake silence";
@@ -209,7 +271,7 @@ describe("SilenceFormStore.data.isValid", () => {
});
it("isValid returns 'false' if matchers list is pupulated when a matcher without any name", () => {
- store.data.alertmanagers = [MockAlertmanager];
+ store.data.alertmanagers = [MockAlertmanagerOption];
store.data.matchers = [MockMatcher("", ["bar"])];
store.data.author = "me@example.com";
store.data.comment = "fake silence";
@@ -217,7 +279,7 @@ describe("SilenceFormStore.data.isValid", () => {
});
it("isValid returns 'false' if matchers list is pupulated when a matcher without any value ([])", () => {
- store.data.alertmanagers = [MockAlertmanager];
+ store.data.alertmanagers = [MockAlertmanagerOption];
store.data.matchers = [MockMatcher("foo", [])];
store.data.author = "me@example.com";
store.data.comment = "fake silence";
@@ -225,7 +287,7 @@ describe("SilenceFormStore.data.isValid", () => {
});
it("isValid returns 'false' if matchers list is pupulated when a matcher with empty value ([''])", () => {
- store.data.alertmanagers = [MockAlertmanager];
+ store.data.alertmanagers = [MockAlertmanagerOption];
store.data.matchers = [MockMatcher("foo", [])];
store.data.author = "me@example.com";
store.data.comment = "fake silence";
@@ -233,7 +295,7 @@ describe("SilenceFormStore.data.isValid", () => {
});
it("isValid returns 'false' if author is empty", () => {
- store.data.alertmanagers = [MockAlertmanager];
+ store.data.alertmanagers = [MockAlertmanagerOption];
store.data.matchers = [MockMatcher("foo", ["bar"])];
store.data.author = "";
store.data.comment = "fake silence";
@@ -241,7 +303,7 @@ describe("SilenceFormStore.data.isValid", () => {
});
it("isValid returns 'false' if comment is empty", () => {
- store.data.alertmanagers = [MockAlertmanager];
+ store.data.alertmanagers = [MockAlertmanagerOption];
store.data.matchers = [MockMatcher("foo", ["bar"])];
store.data.author = "me@example.com";
store.data.comment = "";
@@ -249,7 +311,7 @@ describe("SilenceFormStore.data.isValid", () => {
});
it("isValid returns 'true' if all fileds are set", () => {
- store.data.alertmanagers = [MockAlertmanager];
+ store.data.alertmanagers = [MockAlertmanagerOption];
store.data.matchers = [MockMatcher("foo", ["bar"])];
store.data.author = "me@example.com";
store.data.comment = "fake silence";
diff --git a/ui/src/Stores/__snapshots__/SilenceFormStore.test.js.snap b/ui/src/Stores/__snapshots__/SilenceFormStore.test.js.snap
index ed4b8cca6..2d39dc49c 100644
--- a/ui/src/Stores/__snapshots__/SilenceFormStore.test.js.snap
+++ b/ui/src/Stores/__snapshots__/SilenceFormStore.test.js.snap
@@ -3,7 +3,7 @@
exports[`SilenceFormStore.data toAlertmanagerPayload creates payload that matches snapshot 1`] = `
Object {
"comment": "toAlertmanagerPayload test",
- "createdBy": "",
+ "createdBy": "me@example.com",
"endsAt": "2000-02-01T01:00:00.000Z",
"matchers": Array [
Object {
diff --git a/ui/src/__mocks__/Alerts.js b/ui/src/__mocks__/Alerts.js
index f0dedab7e..ae8a012de 100644
--- a/ui/src/__mocks__/Alerts.js
+++ b/ui/src/__mocks__/Alerts.js
@@ -49,4 +49,32 @@ const MockAlertGroup = (
}
});
-export { MockAnnotation, MockAlert, MockAlertGroup };
+const MockSilence = () => ({
+ comment: "Mocked Silence",
+ createdAt: "0001-01-01T00:00:00Z",
+ createdBy: "me@example.com",
+ startsAt: "2000-01-01T00:00:00Z",
+ endsAt: "2000-01-01T01:00:00Z",
+ id: "04d37636-2350-4878-b382-e0b50353230f",
+ jiraID: "",
+ jiraURL: "",
+ matchers: [
+ { name: "foo", value: "bar", isRegex: false },
+ { name: "baz", value: "regex", isRegex: true }
+ ]
+});
+
+const MockAlertmanager = () => ({
+ name: "default",
+ uri: "http://localhost",
+ publicURI: "http://am.example.com",
+ error: ""
+});
+
+export {
+ MockAnnotation,
+ MockAlert,
+ MockAlertGroup,
+ MockSilence,
+ MockAlertmanager
+};