From 2b963c65d1df1c9e3b90c167fcdf1dafb79c1ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Tue, 24 Nov 2020 19:21:55 +0000 Subject: [PATCH] feat(ui): allow customising ack silence comment Fixes #2369 --- CHANGELOG.md | 3 ++ .../testscript/059_log_full_config_env.txt | 4 +- .../testscript/060_log_full_config_file.txt | 4 +- ...61_log_full_config_file_invalid_values.txt | 2 +- .../testscript/065_proxy-with-readonly.txt | 2 +- cmd/karma/tests/testscript/066_proxy.txt | 2 +- cmd/karma/tests/testscript/067_readonly.txt | 2 +- cmd/karma/tests/testscript/068_sentry.txt | 2 +- .../tests/testscript/070_upper_case_keys.txt | 2 +- cmd/karma/views.go | 2 +- cmd/karma/views_test.go | 2 +- demo/karma.yaml | 1 - docs/CONFIGURATION.md | 20 ++++++--- internal/config/config.go | 6 +-- internal/config/config_test.go | 2 +- internal/config/models.go | 8 ++-- internal/models/api.go | 2 +- ui/src/Components/AlertAck/index.test.tsx | 42 ++++++++++++------- ui/src/Components/AlertAck/index.tsx | 10 ++--- ui/src/Models/APITypes.ts | 2 +- ui/src/Stores/AlertStore.ts | 2 +- ui/src/__fixtures__/Fetch.ts | 2 +- 22 files changed, 74 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40e5e57d3..4630d6015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,3 +11,6 @@ - ghcr.io/prymitive/karma is now used as the primary repository for docker images instead of Docker Hub +- `alertAcknowledgement:commentPrefix` config option was replaced by + `alertAcknowledgement:comment` that can be used to customise the entire + comment. diff --git a/cmd/karma/tests/testscript/059_log_full_config_env.txt b/cmd/karma/tests/testscript/059_log_full_config_env.txt index ded1cd3a3..c19c44adf 100644 --- a/cmd/karma/tests/testscript/059_log_full_config_env.txt +++ b/cmd/karma/tests/testscript/059_log_full_config_env.txt @@ -12,7 +12,7 @@ env ALERTMANAGER_TIMEOUT=10s env ALERTACKNOWLEDGEMENT_ENABLED=true env ALERTACKNOWLEDGEMENT_DURATION=5m env ALERTACKNOWLEDGEMENT_AUTHOR=karma -env ALERTACKNOWLEDGEMENT_COMMENTPREFIX=ACK +env ALERTACKNOWLEDGEMENT_COMMENT="ACK! This alert was acknowledged via unit tests" env ANNOTATIONS_DEFAULT_HIDDEN=true env ANNOTATIONS_HIDDEN='help summary' @@ -106,7 +106,7 @@ level=info msg="alertAcknowledgement:" level=info msg=" enabled: true" level=info msg=" duration: 5m0s" level=info msg=" author: karma" -level=info msg=" commentPrefix: ACK" +level=info msg=" comment: '\"ACK!'" level=info msg="annotations:" level=info msg=" default:" level=info msg=" hidden: true" diff --git a/cmd/karma/tests/testscript/060_log_full_config_file.txt b/cmd/karma/tests/testscript/060_log_full_config_file.txt index 553e3de43..bc6e64c2d 100644 --- a/cmd/karma/tests/testscript/060_log_full_config_file.txt +++ b/cmd/karma/tests/testscript/060_log_full_config_file.txt @@ -93,7 +93,7 @@ level=info msg="alertAcknowledgement:" level=info msg=" enabled: true" level=info msg=" duration: 7m0s" level=info msg=" author: karma" -level=info msg=" commentPrefix: ACK!" +level=info msg=" comment: ACK! This is comment" level=info msg="annotations:" level=info msg=" default:" level=info msg=" hidden: true" @@ -261,7 +261,7 @@ alertAcknowledgement: enabled: true duration: 7m0s author: karma - commentPrefix: ACK! + comment: ACK! This is comment annotations: default: hidden: true diff --git a/cmd/karma/tests/testscript/061_log_full_config_file_invalid_values.txt b/cmd/karma/tests/testscript/061_log_full_config_file_invalid_values.txt index b6ffef8ce..edfe3d459 100644 --- a/cmd/karma/tests/testscript/061_log_full_config_file_invalid_values.txt +++ b/cmd/karma/tests/testscript/061_log_full_config_file_invalid_values.txt @@ -37,7 +37,7 @@ alertAcknowledgement: enabled: zzz duration: 7m0s author: karma - commentPrefix: ACK! + comment: comment annotations: default: hidden: z diff --git a/cmd/karma/tests/testscript/065_proxy-with-readonly.txt b/cmd/karma/tests/testscript/065_proxy-with-readonly.txt index b7490a9e4..930d7aa50 100644 --- a/cmd/karma/tests/testscript/065_proxy-with-readonly.txt +++ b/cmd/karma/tests/testscript/065_proxy-with-readonly.txt @@ -39,7 +39,7 @@ level=info msg="alertAcknowledgement:" level=info msg=" enabled: false" level=info msg=" duration: 15m0s" level=info msg=" author: karma" -level=info msg=" commentPrefix: ACK!" +level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%" level=info msg="annotations:" level=info msg=" default:" level=info msg=" hidden: false" diff --git a/cmd/karma/tests/testscript/066_proxy.txt b/cmd/karma/tests/testscript/066_proxy.txt index 4923cfa8b..740352a54 100644 --- a/cmd/karma/tests/testscript/066_proxy.txt +++ b/cmd/karma/tests/testscript/066_proxy.txt @@ -39,7 +39,7 @@ level=info msg="alertAcknowledgement:" level=info msg=" enabled: false" level=info msg=" duration: 15m0s" level=info msg=" author: karma" -level=info msg=" commentPrefix: ACK!" +level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%" level=info msg="annotations:" level=info msg=" default:" level=info msg=" hidden: false" diff --git a/cmd/karma/tests/testscript/067_readonly.txt b/cmd/karma/tests/testscript/067_readonly.txt index ed0f0a3d8..a01b18032 100644 --- a/cmd/karma/tests/testscript/067_readonly.txt +++ b/cmd/karma/tests/testscript/067_readonly.txt @@ -39,7 +39,7 @@ level=info msg="alertAcknowledgement:" level=info msg=" enabled: false" level=info msg=" duration: 15m0s" level=info msg=" author: karma" -level=info msg=" commentPrefix: ACK!" +level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%" level=info msg="annotations:" level=info msg=" default:" level=info msg=" hidden: false" diff --git a/cmd/karma/tests/testscript/068_sentry.txt b/cmd/karma/tests/testscript/068_sentry.txt index f195e244f..05efab7a9 100644 --- a/cmd/karma/tests/testscript/068_sentry.txt +++ b/cmd/karma/tests/testscript/068_sentry.txt @@ -41,7 +41,7 @@ level=info msg="alertAcknowledgement:" level=info msg=" enabled: false" level=info msg=" duration: 15m0s" level=info msg=" author: karma" -level=info msg=" commentPrefix: ACK!" +level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%" level=info msg="annotations:" level=info msg=" default:" level=info msg=" hidden: false" diff --git a/cmd/karma/tests/testscript/070_upper_case_keys.txt b/cmd/karma/tests/testscript/070_upper_case_keys.txt index a81ef9f65..160d46d1f 100644 --- a/cmd/karma/tests/testscript/070_upper_case_keys.txt +++ b/cmd/karma/tests/testscript/070_upper_case_keys.txt @@ -39,7 +39,7 @@ level=info msg="alertAcknowledgement:" level=info msg=" enabled: false" level=info msg=" duration: 15m0s" level=info msg=" author: karma" -level=info msg=" commentPrefix: ACK!" +level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%" level=info msg="annotations:" level=info msg=" default:" level=info msg=" hidden: false" diff --git a/cmd/karma/views.go b/cmd/karma/views.go index a6750e53a..28415b9c1 100644 --- a/cmd/karma/views.go +++ b/cmd/karma/views.go @@ -167,7 +167,7 @@ func alerts(w http.ResponseWriter, r *http.Request) { Enabled: config.Config.AlertAcknowledgement.Enabled, DurationSeconds: int(config.Config.AlertAcknowledgement.Duration.Seconds()), Author: config.Config.AlertAcknowledgement.Author, - CommentPrefix: config.Config.AlertAcknowledgement.CommentPrefix, + Comment: config.Config.AlertAcknowledgement.Comment, }, } resp.Authentication = models.AuthenticationInfo{ diff --git a/cmd/karma/views_test.go b/cmd/karma/views_test.go index f8900bf3d..730ed840b 100644 --- a/cmd/karma/views_test.go +++ b/cmd/karma/views_test.go @@ -857,7 +857,7 @@ func TestEmptySettings(t *testing.T) { Enabled: false, DurationSeconds: 900, Author: "karma", - CommentPrefix: "ACK!", + Comment: "ACK! This alert was acknowledged using karma on %NOW%", }, } diff --git a/demo/karma.yaml b/demo/karma.yaml index ed2fea056..c9ba109c4 100644 --- a/demo/karma.yaml +++ b/demo/karma.yaml @@ -28,7 +28,6 @@ alertAcknowledgement: enabled: true duration: 15m0s author: karma-ack - commentPrefix: ACK! annotations: hidden: - help diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 351ed8896..3dc99759f 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -412,7 +412,7 @@ alertAcknowledgement: enabled: bool duration: duration author: string - commentPrefix: string + comment: string ``` - `enabled` - setting it to true will enable creation of short lived @@ -421,8 +421,8 @@ alertAcknowledgement: [time.Duration](https://golang.org/pkg/time/#ParseDuration) format. - `author` - default author for acknowledgement silences. If user set the author field on the silence form then that value will be used instead. -- `commentPrefix` - a string that will be added as a prefix to autogenerated - silence comment (optional). +- `comment` - custom comment used for acknowledgement silences (optional). + If the comment contains `%NOW%` it will be replaced by current timestamp. Defaults: @@ -431,7 +431,17 @@ alertAcknowledgement: enabled: false duration: 15m0s author: karma - commentPrefix: ACK! + comment: ACK! This alert was acknowledged using karma +``` + +Example with timestamp in the comment: + +```YAML +alertAcknowledgement: + enabled: false + duration: 15m0s + author: karma + comment: ACK! This alert was acknowledged using karma on %NOW% ``` A common problem is setting a correct duration for the silence. @@ -446,7 +456,7 @@ short lived acknowledgement silences if there are alerts firing against those silences, which means that the user doesn't need to worry about setting proper duration for such silences. To use it run an instance of kthxbye with every alertmanager instance or -cluster and configure it to use the same comment prefix as `commentPrefix`. +cluster and configure it to use the same comment prefix in `comment`. With this setup when user clicks to acknowledge an alert karma will create a short lived silence and kthxbye will keep that silence in Alertmanager until there are no alerts matching it, meaning that the issue was resolved. diff --git a/internal/config/config.go b/internal/config/config.go index 00c2759a1..f98c68de4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -58,7 +58,7 @@ func SetupFlags(f *pflag.FlagSet) { f.Bool("alertAcknowledgement.enabled", false, "Enable alert acknowledging") f.Duration("alertAcknowledgement.duration", time.Minute*15, "Initial silence duration when acknowledging alerts with short lived silences") f.String("alertAcknowledgement.author", "karma", "Default silence author when acknowledging alerts with short lived silences") - f.String("alertAcknowledgement.commentPrefix", "ACK!", "Comment prefix used when acknowledging alerts with short lived silences") + f.String("alertAcknowledgement.comment", "ACK! This alert was acknowledged using karma on %NOW%", "Comment used when acknowledging alerts with short lived silences") f.String("authorization.acl.silences", "", "Path to silence ACL config file") @@ -193,8 +193,8 @@ func readEnvVariables(k *koanf.Koanf) { return "alertAcknowledgement.duration" case "ALERTACKNOWLEDGEMENT_AUTHOR": return "alertAcknowledgement.author" - case "ALERTACKNOWLEDGEMENT_COMMENTPREFIX": - return "alertAcknowledgement.commentPrefix" + case "ALERTACKNOWLEDGEMENT_COMMENT": + return "alertAcknowledgement.comment" case "AUTHENTICATION_HEADER_VALUE_RE": return "authentication.header.value_re" case "SILENCEFORM_STRIP_LABELS": diff --git a/internal/config/config_test.go b/internal/config/config_test.go index e9df3f8f4..900373cea 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -52,7 +52,7 @@ alertAcknowledgement: enabled: false duration: 15m0s author: karma - commentPrefix: ACK! + comment: ACK! This alert was acknowledged using karma on %NOW% annotations: default: hidden: true diff --git a/internal/config/models.go b/internal/config/models.go index f0c164628..f149aa821 100644 --- a/internal/config/models.go +++ b/internal/config/models.go @@ -81,10 +81,10 @@ type configSchema struct { CORS AlertmanagerCORS `yaml:"-" koanf:"cors"` } AlertAcknowledgement struct { - Enabled bool - Duration time.Duration - Author string - CommentPrefix string `yaml:"commentPrefix" koanf:"commentPrefix"` + Enabled bool + Duration time.Duration + Author string + Comment string } `yaml:"alertAcknowledgement" koanf:"alertAcknowledgement"` Annotations struct { Default struct { diff --git a/internal/models/api.go b/internal/models/api.go index 872c6470d..dfec10713 100644 --- a/internal/models/api.go +++ b/internal/models/api.go @@ -281,7 +281,7 @@ type AlertAcknowledgementSettings struct { Enabled bool `json:"enabled"` DurationSeconds int `json:"durationSeconds"` Author string `json:"author"` - CommentPrefix string `json:"commentPrefix"` + Comment string `json:"comment"` } // Settings is used to export karma configuration that is used by UI diff --git a/ui/src/Components/AlertAck/index.test.tsx b/ui/src/Components/AlertAck/index.test.tsx index f339e2008..03a27ccf5 100644 --- a/ui/src/Components/AlertAck/index.test.tsx +++ b/ui/src/Components/AlertAck/index.test.tsx @@ -31,7 +31,7 @@ beforeEach(() => { enabled: true, durationSeconds: 123, author: "default author", - commentPrefix: "PREFIX", + comment: "COMMENT", }; alertStore.data.setUpstreams({ counters: { total: 1, healthy: 1, failed: 0 }, @@ -284,8 +284,7 @@ describe("", () => { silenceFormStore.data.setAuthor("karma/ui"); await MountAndClick(); expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({ - comment: - "PREFIX This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT", + comment: "COMMENT", createdBy: "karma/ui", endsAt: "2000-02-01T00:02:03.000Z", matchers: [ @@ -299,11 +298,29 @@ describe("", () => { it("uses settings when generating payload", async () => { alertStore.settings.values.alertAcknowledgement.durationSeconds = 237; alertStore.settings.values.alertAcknowledgement.author = "me"; - alertStore.settings.values.alertAcknowledgement.commentPrefix = ""; + alertStore.settings.values.alertAcknowledgement.comment = "comment"; + await MountAndClick(); + expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({ + comment: "comment", + createdBy: "me", + endsAt: "2000-02-01T00:03:57.000Z", + matchers: [ + { isRegex: false, name: "alertname", value: "Fake Alert" }, + { isRegex: true, name: "foo", value: "(bar|baz)" }, + ], + startsAt: "2000-02-01T00:00:00.000Z", + }); + }); + + it("injects timestamp when configured", async () => { + alertStore.settings.values.alertAcknowledgement.durationSeconds = 237; + alertStore.settings.values.alertAcknowledgement.author = "me"; + alertStore.settings.values.alertAcknowledgement.comment = + "ACK! This alert was acknowledged using karma on %NOW%"; await MountAndClick(); expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({ comment: - "This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT", + "ACK! This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT", createdBy: "me", endsAt: "2000-02-01T00:03:57.000Z", matchers: [ @@ -319,11 +336,10 @@ describe("", () => { alertStore.info.authentication.username = "auth@example.com"; alertStore.settings.values.alertAcknowledgement.durationSeconds = 222; alertStore.settings.values.alertAcknowledgement.author = "me"; - alertStore.settings.values.alertAcknowledgement.commentPrefix = "FOO:"; + alertStore.settings.values.alertAcknowledgement.comment = "FOO: bar"; await MountAndClick(); expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({ - comment: - "FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT", + comment: "FOO: bar", createdBy: "auth@example.com", endsAt: "2000-02-01T00:03:42.000Z", matchers: [ @@ -339,12 +355,11 @@ describe("", () => { alertStore.info.authentication.username = "wrong"; alertStore.settings.values.alertAcknowledgement.durationSeconds = 222; alertStore.settings.values.alertAcknowledgement.author = "me"; - alertStore.settings.values.alertAcknowledgement.commentPrefix = "FOO:"; + alertStore.settings.values.alertAcknowledgement.comment = "FOO: bar"; silenceFormStore.data.setAuthor("bob@example.com"); await MountAndClick(); expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({ - comment: - "FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT", + comment: "FOO: bar", createdBy: "bob@example.com", endsAt: "2000-02-01T00:03:42.000Z", matchers: [ @@ -358,12 +373,11 @@ describe("", () => { it("uses default author as fallback", async () => { alertStore.settings.values.alertAcknowledgement.durationSeconds = 222; alertStore.settings.values.alertAcknowledgement.author = "me"; - alertStore.settings.values.alertAcknowledgement.commentPrefix = "FOO:"; + alertStore.settings.values.alertAcknowledgement.comment = "FOO: bar"; silenceFormStore.data.setAuthor(""); await MountAndClick(); expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({ - comment: - "FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT", + comment: "FOO: bar", createdBy: "me", endsAt: "2000-02-01T00:03:42.000Z", matchers: [ diff --git a/ui/src/Components/AlertAck/index.tsx b/ui/src/Components/AlertAck/index.tsx index d4db005f5..192fe0b7e 100644 --- a/ui/src/Components/AlertAck/index.tsx +++ b/ui/src/Components/AlertAck/index.tsx @@ -74,19 +74,17 @@ const AlertAck: FC<{ const durationSeconds = toJS( alertStore.settings.values.alertAcknowledgement.durationSeconds ); - const commentPrefix = toJS( - alertStore.settings.values.alertAcknowledgement.commentPrefix - ); const now = new Date(); + const comment = toJS( + alertStore.settings.values.alertAcknowledgement.comment + ).replace("%NOW%", now.toUTCString()); c.push({ payload: GenerateAlertmanagerSilenceData( now, addSeconds(now, durationSeconds), MatchersFromGroup(group, [], group.alerts, true), author, - `${ - commentPrefix ? commentPrefix + " " : "" - }This alert was acknowledged using karma on ${now.toUTCString()}` + comment ), clusterName: clusterName, members: clusterMembers, diff --git a/ui/src/Models/APITypes.ts b/ui/src/Models/APITypes.ts index dde3cc79a..8ec98f8e4 100644 --- a/ui/src/Models/APITypes.ts +++ b/ui/src/Models/APITypes.ts @@ -182,7 +182,7 @@ export interface APISettingsT { enabled: boolean; durationSeconds: number; author: string; - commentPrefix: string; + comment: string; }; } diff --git a/ui/src/Stores/AlertStore.ts b/ui/src/Stores/AlertStore.ts index 406daf174..66b7d7a5a 100644 --- a/ui/src/Stores/AlertStore.ts +++ b/ui/src/Stores/AlertStore.ts @@ -413,7 +413,7 @@ class AlertStore { enabled: false as boolean, durationSeconds: 900, author: "karma / author missing", - commentPrefix: "", + comment: "ACK! This alert was acknowledged using karma", }, }, }, diff --git a/ui/src/__fixtures__/Fetch.ts b/ui/src/__fixtures__/Fetch.ts index feada2313..b8e68898e 100644 --- a/ui/src/__fixtures__/Fetch.ts +++ b/ui/src/__fixtures__/Fetch.ts @@ -73,7 +73,7 @@ const EmptyAPIResponse = (): APIAlertsResponseT => ({ enabled: false, durationSeconds: 900, author: "karma / author missing", - commentPrefix: "", + comment: "ACK! Mock comment", }, staticColorLabels: ["job"], annotationsDefaultHidden: false,