mirror of
https://github.com/prometheus/alertmanager
synced 2025-02-03 20:21:43 +00:00
feat: implement webhook_url_file for discord and msteams (#3555)
* feat: implement webhook_url_file for discord implements #3482 Signed-off-by: Philipp Born <git@pborn.eu> * feat: implement webhook_url_file for msteams implements #3536 Signed-off-by: Philipp Born <git@pborn.eu> --------- Signed-off-by: Philipp Born <git@pborn.eu>
This commit is contained in:
parent
5eca7d5170
commit
3d49ff83c7
@ -216,8 +216,9 @@ func (c *WebexConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
type DiscordConfig struct {
|
||||
NotifierConfig `yaml:",inline" json:",inline"`
|
||||
|
||||
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
|
||||
WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"`
|
||||
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
|
||||
WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"`
|
||||
WebhookURLFile string `yaml:"webhook_url_file,omitempty" json:"webhook_url_file,omitempty"`
|
||||
|
||||
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
||||
Message string `yaml:"message,omitempty" json:"message,omitempty"`
|
||||
@ -227,7 +228,19 @@ type DiscordConfig struct {
|
||||
func (c *DiscordConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
*c = DefaultDiscordConfig
|
||||
type plain DiscordConfig
|
||||
return unmarshal((*plain)(c))
|
||||
if err := unmarshal((*plain)(c)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.WebhookURL == nil && c.WebhookURLFile == "" {
|
||||
return fmt.Errorf("one of webhook_url or webhook_url_file must be configured")
|
||||
}
|
||||
|
||||
if c.WebhookURL != nil && len(c.WebhookURLFile) > 0 {
|
||||
return fmt.Errorf("at most one of webhook_url & webhook_url_file must be configured")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EmailConfig configures notifications via mail.
|
||||
@ -787,6 +800,7 @@ type MSTeamsConfig struct {
|
||||
NotifierConfig `yaml:",inline" json:",inline"`
|
||||
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
|
||||
WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"`
|
||||
WebhookURLFile string `yaml:"webhook_url_file,omitempty" json:"webhook_url_file,omitempty"`
|
||||
|
||||
Title string `yaml:"title,omitempty" json:"title,omitempty"`
|
||||
Summary string `yaml:"summary,omitempty" json:"summary,omitempty"`
|
||||
@ -796,5 +810,17 @@ type MSTeamsConfig struct {
|
||||
func (c *MSTeamsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
*c = DefaultMSTeamsConfig
|
||||
type plain MSTeamsConfig
|
||||
return unmarshal((*plain)(c))
|
||||
if err := unmarshal((*plain)(c)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.WebhookURL == nil && c.WebhookURLFile == "" {
|
||||
return fmt.Errorf("one of webhook_url or webhook_url_file must be configured")
|
||||
}
|
||||
|
||||
if c.WebhookURL != nil && len(c.WebhookURLFile) > 0 {
|
||||
return fmt.Errorf("at most one of webhook_url & webhook_url_file must be configured")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -670,7 +670,9 @@ Discord notifications are sent via the [Discord webhook API](https://discord.com
|
||||
[ send_resolved: <boolean> | default = true ]
|
||||
|
||||
# The Discord webhook URL.
|
||||
# webhook_url and webhook_url_file are mutually exclusive.
|
||||
webhook_url: <secret>
|
||||
webhook_url_file: <filepath>
|
||||
|
||||
# Message title template.
|
||||
[ title: <tmpl_string> | default = '{{ template "discord.default.title" . }}' ]
|
||||
@ -735,7 +737,9 @@ Microsoft Teams notifications are sent via the [Incoming Webhooks](https://learn
|
||||
[ send_resolved: <boolean> | default = true ]
|
||||
|
||||
# The incoming webhook URL.
|
||||
# webhook_url and webhook_url_file are mutually exclusive.
|
||||
[ webhook_url: <secret> ]
|
||||
[ webhook_url_file: <filepath> ]
|
||||
|
||||
# Message title template.
|
||||
[ title: <tmpl_string> | default = '{{ template "msteams.default.title" . }}' ]
|
||||
|
@ -17,7 +17,10 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
@ -120,6 +123,17 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
|
||||
color = colorGreen
|
||||
}
|
||||
|
||||
var url string
|
||||
if n.conf.WebhookURL != nil {
|
||||
url = n.conf.WebhookURL.String()
|
||||
} else {
|
||||
content, err := os.ReadFile(n.conf.WebhookURLFile)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("read webhook_url_file: %w", err)
|
||||
}
|
||||
url = strings.TrimSpace(string(content))
|
||||
}
|
||||
|
||||
w := webhook{
|
||||
Embeds: []webhookEmbed{{
|
||||
Title: title,
|
||||
@ -133,7 +147,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := notify.PostJSON(ctx, n.client, n.webhookURL.String(), &payload)
|
||||
resp, err := notify.PostJSON(ctx, n.client, url, &payload)
|
||||
if err != nil {
|
||||
return true, notify.RedactURL(err)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -127,3 +128,43 @@ func TestDiscordTemplating(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscordRedactedURL(t *testing.T) {
|
||||
ctx, u, fn := test.GetContextWithCancelingURL()
|
||||
defer fn()
|
||||
|
||||
secret := "secret"
|
||||
notifier, err := New(
|
||||
&config.DiscordConfig{
|
||||
WebhookURL: &config.SecretURL{URL: u},
|
||||
HTTPConfig: &commoncfg.HTTPClientConfig{},
|
||||
},
|
||||
test.CreateTmpl(t),
|
||||
log.NewNopLogger(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
test.AssertNotifyLeaksNoSecret(ctx, t, notifier, secret)
|
||||
}
|
||||
|
||||
func TestDiscordReadingURLFromFile(t *testing.T) {
|
||||
ctx, u, fn := test.GetContextWithCancelingURL()
|
||||
defer fn()
|
||||
|
||||
f, err := os.CreateTemp("", "webhook_url")
|
||||
require.NoError(t, err, "creating temp file failed")
|
||||
_, err = f.WriteString(u.String() + "\n")
|
||||
require.NoError(t, err, "writing to temp file failed")
|
||||
|
||||
notifier, err := New(
|
||||
&config.DiscordConfig{
|
||||
WebhookURLFile: f.Name(),
|
||||
HTTPConfig: &commoncfg.HTTPClientConfig{},
|
||||
},
|
||||
test.CreateTmpl(t),
|
||||
log.NewNopLogger(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
test.AssertNotifyLeaksNoSecret(ctx, t, notifier, u.String())
|
||||
}
|
||||
|
@ -17,8 +17,11 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
@ -113,6 +116,17 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
|
||||
color = colorGreen
|
||||
}
|
||||
|
||||
var url string
|
||||
if n.conf.WebhookURL != nil {
|
||||
url = n.conf.WebhookURL.String()
|
||||
} else {
|
||||
content, err := os.ReadFile(n.conf.WebhookURLFile)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("read webhook_url_file: %w", err)
|
||||
}
|
||||
url = strings.TrimSpace(string(content))
|
||||
}
|
||||
|
||||
t := teamsMessage{
|
||||
Context: "http://schema.org/extensions",
|
||||
Type: "MessageCard",
|
||||
@ -127,7 +141,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := n.postJSONFunc(ctx, n.client, n.webhookURL.String(), &payload)
|
||||
resp, err := n.postJSONFunc(ctx, n.client, url, &payload)
|
||||
if err != nil {
|
||||
return true, notify.RedactURL(err)
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -192,3 +193,43 @@ func TestNotifier_Notify_WithReason(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMSTeamsRedactedURL(t *testing.T) {
|
||||
ctx, u, fn := test.GetContextWithCancelingURL()
|
||||
defer fn()
|
||||
|
||||
secret := "secret"
|
||||
notifier, err := New(
|
||||
&config.MSTeamsConfig{
|
||||
WebhookURL: &config.SecretURL{URL: u},
|
||||
HTTPConfig: &commoncfg.HTTPClientConfig{},
|
||||
},
|
||||
test.CreateTmpl(t),
|
||||
log.NewNopLogger(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
test.AssertNotifyLeaksNoSecret(ctx, t, notifier, secret)
|
||||
}
|
||||
|
||||
func TestMSTeamsReadingURLFromFile(t *testing.T) {
|
||||
ctx, u, fn := test.GetContextWithCancelingURL()
|
||||
defer fn()
|
||||
|
||||
f, err := os.CreateTemp("", "webhook_url")
|
||||
require.NoError(t, err, "creating temp file failed")
|
||||
_, err = f.WriteString(u.String() + "\n")
|
||||
require.NoError(t, err, "writing to temp file failed")
|
||||
|
||||
notifier, err := New(
|
||||
&config.MSTeamsConfig{
|
||||
WebhookURLFile: f.Name(),
|
||||
HTTPConfig: &commoncfg.HTTPClientConfig{},
|
||||
},
|
||||
test.CreateTmpl(t),
|
||||
log.NewNopLogger(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
test.AssertNotifyLeaksNoSecret(ctx, t, notifier, u.String())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user