From eef3396b8739253ac9a6f6e9ce2102c703334aef Mon Sep 17 00:00:00 2001 From: patschius Date: Tue, 31 Oct 2023 17:07:37 +0100 Subject: [PATCH 1/7] Adding ntfy notifications to keel Extending templates and values for new Env Variable NTFY_WEBHOOK_URL --- chart/keel/templates/deployment.yaml | 5 +++++ chart/keel/values.yaml | 5 +++++ constants/constants.go | 3 +++ deployment/deployment-template.yaml | 3 +++ 4 files changed, 16 insertions(+) diff --git a/chart/keel/templates/deployment.yaml b/chart/keel/templates/deployment.yaml index e6851fe8c..1088d5b1f 100644 --- a/chart/keel/templates/deployment.yaml +++ b/chart/keel/templates/deployment.yaml @@ -113,6 +113,11 @@ spec: - name: WEBHOOK_ENDPOINT value: "{{ .Values.webhook.endpoint }}" {{- end }} +{{- if .Values.ntfy.enabled }} + # Enable webhook endpoint + - name: WEBHOOK_ENDPOINT + value: "{{ .Values.ntfy.webhookUrl }}" +{{- end }} {{- if .Values.mattermost.enabled }} # Enable mattermost endpoint - name: MATTERMOST_ENDPOINT diff --git a/chart/keel/values.yaml b/chart/keel/values.yaml index 79aa3d6f6..258bc57f5 100644 --- a/chart/keel/values.yaml +++ b/chart/keel/values.yaml @@ -98,6 +98,11 @@ discord: enabled: false webhookUrl: "" +# ntfy notifications +ntfy: + enabled: false + webhookUrl: "" + # Mail notifications mail: enabled: false diff --git a/constants/constants.go b/constants/constants.go index 787b7cbba..731dd29de 100644 --- a/constants/constants.go +++ b/constants/constants.go @@ -37,6 +37,9 @@ const ( // Discord webhook url, see https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks EnvDiscordWebhookUrl = "DISCORD_WEBHOOK_URL" + // Discord webhook url, see https://docs.ntfy.sh/publish/ + EnvNtfyWebhookUrl = "NTFY_WEBHOOK_URL" + // Mail notification settings EnvMailTo = "MAIL_TO" EnvMailFrom = "MAIL_FROM" diff --git a/deployment/deployment-template.yaml b/deployment/deployment-template.yaml index 2648513d4..839c76a25 100644 --- a/deployment/deployment-template.yaml +++ b/deployment/deployment-template.yaml @@ -185,6 +185,9 @@ spec: # Enable MS Teams webhook endpoint - name: TEAMS_WEBHOOK_URL value: "{{ .teams_webhook_url }}" + # Enable ntfy webhook endpoint + - name: NTFY_WEBHOOK_URL + value: "{{ .ntfy_webhook_url }}" - name: SLACK_TOKEN value: "{{ .slack_token }}" - name: SLACK_CHANNELS From bc4250406189d385c0d00d7ff40cd0f495f88502 Mon Sep 17 00:00:00 2001 From: patschius Date: Tue, 31 Oct 2023 17:08:56 +0100 Subject: [PATCH 2/7] Correcting copy paste mistake in constants comment --- constants/constants.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants/constants.go b/constants/constants.go index 731dd29de..801d82abf 100644 --- a/constants/constants.go +++ b/constants/constants.go @@ -37,7 +37,7 @@ const ( // Discord webhook url, see https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks EnvDiscordWebhookUrl = "DISCORD_WEBHOOK_URL" - // Discord webhook url, see https://docs.ntfy.sh/publish/ + // ntfy webhook url, see https://docs.ntfy.sh/publish/ EnvNtfyWebhookUrl = "NTFY_WEBHOOK_URL" // Mail notification settings From 466346f9558c66217e0b237ce39813e92b286650 Mon Sep 17 00:00:00 2001 From: patschius Date: Tue, 31 Oct 2023 17:11:00 +0100 Subject: [PATCH 3/7] Adding, (in previous commit) missed go implementation for ntfy Notificiations. --- extension/notification/ntfy/ntfy.go | 82 ++++++++++++++++++++++++ extension/notification/ntfy/ntfy_test.go | 59 +++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 extension/notification/ntfy/ntfy.go create mode 100644 extension/notification/ntfy/ntfy_test.go diff --git a/extension/notification/ntfy/ntfy.go b/extension/notification/ntfy/ntfy.go new file mode 100644 index 000000000..bd61230dc --- /dev/null +++ b/extension/notification/ntfy/ntfy.go @@ -0,0 +1,82 @@ +package discord + +import ( + "fmt" + "net/http" + "net/url" + "os" + "strings" + "time" + + "github.com/keel-hq/keel/constants" + "github.com/keel-hq/keel/extension/notification" + "github.com/keel-hq/keel/types" + + log "github.com/sirupsen/logrus" +) + +const timeout = 5 * time.Second + +type sender struct { + endpoint string + client *http.Client +} + +// Config represents the configuration of a Discord Webhook Sender. +type Config struct { + Endpoint string +} + +func init() { + notification.RegisterSender("ntfy", &sender{}) +} + +func (s *sender) Configure(config *notification.Config) (bool, error) { + // Get configuration + var httpConfig Config + + if os.Getenv(constants.EnvNtfyWebhookUrl) != "" { + httpConfig.Endpoint = os.Getenv(constants.EnvNtfyWebhookUrl) + } else { + return false, nil + } + // Validate endpoint URL. + if httpConfig.Endpoint == "" { + return false, nil + } + if _, err := url.ParseRequestURI(httpConfig.Endpoint); err != nil { + return false, fmt.Errorf("could not parse endpoint URL: %s", err) + } + s.endpoint = httpConfig.Endpoint + + // Setup HTTP client + s.client = &http.Client{ + Transport: http.DefaultTransport, + Timeout: timeout, + } + + log.WithFields(log.Fields{ + "name": "ntfy", + "endpoint": s.endpoint, + }).Info("extension.notification.ntfy: sender configured") + return true, nil +} + +func (s *sender) Send(event types.EventNotification) error { + + req, _ := http.NewRequest("POST", s.endpoint, strings.NewReader(event.Message)) + req.Header.Set("Title", fmt.Sprintf("%s: %s", event.Type.String(), event.Name)) + req.Header.Set("Tags", "keel") + http.DefaultClient.Do(req) + + resp, err := s.client.Do(req) + if err != nil || resp == nil || (resp.StatusCode != 200 && resp.StatusCode != 204) { + if resp != nil { + return fmt.Errorf("got status %d, expected 200/204", resp.StatusCode) + } + return err + } + defer resp.Body.Close() + + return nil +} diff --git a/extension/notification/ntfy/ntfy_test.go b/extension/notification/ntfy/ntfy_test.go new file mode 100644 index 000000000..b443fe119 --- /dev/null +++ b/extension/notification/ntfy/ntfy_test.go @@ -0,0 +1,59 @@ +package discord + +import ( + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + "github.com/keel-hq/keel/types" +) + +func TestNtfyWebhookRequest(t *testing.T) { + currentTime := time.Now() + handler := func(resp http.ResponseWriter, req *http.Request) { + body, err := io.ReadAll(req.Body) + if err != nil { + t.Errorf("failed to parse body: %s", err) + } + + bodyStr := string(body) + + if !strings.Contains(req.Header.Get("Title"), types.NotificationPreDeploymentUpdate.String()) { + t.Errorf("missing deployment type") + } + + if !strings.Contains(req.Header.Get("Title"), "update deployment") { + t.Errorf("missing deployment type") + } + + if !strings.Contains(req.Header.Get("Tags"), "keel") { + t.Errorf("missing deployment type") + } + + if !strings.Contains(bodyStr, "message here") { + t.Errorf("missing message") + } + + t.Log(bodyStr) + } + + // create test server with handler + ts := httptest.NewServer(http.HandlerFunc(handler)) + defer ts.Close() + + s := &sender{ + endpoint: ts.URL, + client: &http.Client{}, + } + + s.Send(types.EventNotification{ + Name: "update deployment", + Message: "message here", + CreatedAt: currentTime, + Type: types.NotificationPreDeploymentUpdate, + Level: types.LevelDebug, + }) +} From 11be80f4280417c8e662619d80bdef895bf8e56e Mon Sep 17 00:00:00 2001 From: patschius Date: Tue, 31 Oct 2023 17:24:18 +0100 Subject: [PATCH 4/7] Missed adding new notification to list in main.go --- cmd/keel/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/keel/main.go b/cmd/keel/main.go index dbfecde6b..cbadad5cf 100644 --- a/cmd/keel/main.go +++ b/cmd/keel/main.go @@ -43,6 +43,7 @@ import ( _ "github.com/keel-hq/keel/extension/notification/hipchat" _ "github.com/keel-hq/keel/extension/notification/mail" _ "github.com/keel-hq/keel/extension/notification/mattermost" + _ "github.com/keel-hq/keel/extension/notification/ntfy" _ "github.com/keel-hq/keel/extension/notification/slack" _ "github.com/keel-hq/keel/extension/notification/teams" _ "github.com/keel-hq/keel/extension/notification/webhook" From c8558d2f9db36d4833f3a80fee9c9c66da096d5f Mon Sep 17 00:00:00 2001 From: patschius Date: Fri, 3 Nov 2023 11:07:19 +0100 Subject: [PATCH 5/7] Fixed an issue where request would get triggered twice --- extension/notification/ntfy/ntfy.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/notification/ntfy/ntfy.go b/extension/notification/ntfy/ntfy.go index bd61230dc..504b658a3 100644 --- a/extension/notification/ntfy/ntfy.go +++ b/extension/notification/ntfy/ntfy.go @@ -64,10 +64,10 @@ func (s *sender) Configure(config *notification.Config) (bool, error) { func (s *sender) Send(event types.EventNotification) error { - req, _ := http.NewRequest("POST", s.endpoint, strings.NewReader(event.Message)) - req.Header.Set("Title", fmt.Sprintf("%s: %s", event.Type.String(), event.Name)) + req, _ := http.NewRequest("POST", s.endpoint, strings.NewReader(fmt.Sprintf("%s: %s", event.Type.String(), event.Name))) + req.Header.Set("Title", event.Message) req.Header.Set("Tags", "keel") - http.DefaultClient.Do(req) + req.Header.Set("X-Icon", constants.KeelLogoURL) resp, err := s.client.Do(req) if err != nil || resp == nil || (resp.StatusCode != 200 && resp.StatusCode != 204) { From db1bc04241b43d1300bca58d119e7899c586a905 Mon Sep 17 00:00:00 2001 From: patschius Date: Fri, 3 Nov 2023 11:09:33 +0100 Subject: [PATCH 6/7] fix copy paste error in deployment.yaml to correct env variable --- chart/keel/templates/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/keel/templates/deployment.yaml b/chart/keel/templates/deployment.yaml index 1088d5b1f..d22fba73e 100644 --- a/chart/keel/templates/deployment.yaml +++ b/chart/keel/templates/deployment.yaml @@ -115,7 +115,7 @@ spec: {{- end }} {{- if .Values.ntfy.enabled }} # Enable webhook endpoint - - name: WEBHOOK_ENDPOINT + - name: NTFY_WEBHOOK_URL value: "{{ .Values.ntfy.webhookUrl }}" {{- end }} {{- if .Values.mattermost.enabled }} From 99deb5d336612cd487ec8f5cd4c24378fc5cc5c0 Mon Sep 17 00:00:00 2001 From: patschius Date: Fri, 3 Nov 2023 12:25:01 +0100 Subject: [PATCH 7/7] Adapting the unit test ot the changed outputs --- extension/notification/ntfy/ntfy_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extension/notification/ntfy/ntfy_test.go b/extension/notification/ntfy/ntfy_test.go index b443fe119..15b573490 100644 --- a/extension/notification/ntfy/ntfy_test.go +++ b/extension/notification/ntfy/ntfy_test.go @@ -21,19 +21,19 @@ func TestNtfyWebhookRequest(t *testing.T) { bodyStr := string(body) - if !strings.Contains(req.Header.Get("Title"), types.NotificationPreDeploymentUpdate.String()) { - t.Errorf("missing deployment type") + if !strings.Contains(req.Header.Get("Title"), "message here") { + t.Errorf("missing message") } - if !strings.Contains(req.Header.Get("Title"), "update deployment") { + if !strings.Contains(req.Header.Get("Tags"), "keel") { t.Errorf("missing deployment type") } - if !strings.Contains(req.Header.Get("Tags"), "keel") { - t.Errorf("missing deployment type") + if !strings.Contains(bodyStr, "update deployment") { + t.Errorf("missing update deployment") } - if !strings.Contains(bodyStr, "message here") { + if !strings.Contains(bodyStr, types.NotificationPreDeploymentUpdate.String()) { t.Errorf("missing message") }