Skip to content

Commit

Permalink
Merge branch 'main' into superq/v0.28.0-rc.0
Browse files Browse the repository at this point in the history
  • Loading branch information
gotjosh authored Oct 24, 2024
2 parents 4a28c0e + 95655dc commit 540f712
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 8 deletions.
8 changes: 5 additions & 3 deletions config/notifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,11 @@ type DiscordConfig struct {
WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"`
WebhookURLFile string `yaml:"webhook_url_file,omitempty" json:"webhook_url_file,omitempty"`

Content string `yaml:"content,omitempty" json:"content,omitempty"`
Title string `yaml:"title,omitempty" json:"title,omitempty"`
Message string `yaml:"message,omitempty" json:"message,omitempty"`
Content string `yaml:"content,omitempty" json:"content,omitempty"`
Title string `yaml:"title,omitempty" json:"title,omitempty"`
Message string `yaml:"message,omitempty" json:"message,omitempty"`
Username string `yaml:"username,omitempty" json:"username,omitempty"`
AvatarURL string `yaml:"avatar_url,omitempty" json:"avatar_url,omitempty"`
}

// UnmarshalYAML implements the yaml.Unmarshaler interface.
Expand Down
6 changes: 6 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,12 @@ webhook_url_file: <filepath>
# Message content template. Limited to 2000 characters.
[ content: <tmpl_string> | default = '{{ template "discord.default.content" . }}' ]
# Message username.
[ username: <string> | default = '' ]
# Message avatar URL.
[ avatar_url: <string> | default = '' ]
# The HTTP client's configuration.
[ http_config: <http_config> | default = global.http_config ]
```
Expand Down
22 changes: 17 additions & 5 deletions notify/discord/discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"encoding/json"
"fmt"
"net/http"
netUrl "net/url"
"os"
"strings"

Expand Down Expand Up @@ -76,8 +77,10 @@ func New(c *config.DiscordConfig, t *template.Template, l log.Logger, httpOpts .
}

type webhook struct {
Content string `json:"content"`
Embeds []webhookEmbed `json:"embeds"`
Content string `json:"content"`
Embeds []webhookEmbed `json:"embeds"`
Username string `json:"username,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
}

type webhookEmbed struct {
Expand Down Expand Up @@ -137,22 +140,31 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
if n.conf.WebhookURL != nil {
url = n.conf.WebhookURL.String()
} else {
content, err := os.ReadFile(n.conf.WebhookURLFile)
b, err := os.ReadFile(n.conf.WebhookURLFile)
if err != nil {
return false, fmt.Errorf("read webhook_url_file: %w", err)
}
url = strings.TrimSpace(string(content))
url = strings.TrimSpace(string(b))
}

w := webhook{
Content: content,
Content: content,
Username: n.conf.Username,
Embeds: []webhookEmbed{{
Title: title,
Description: description,
Color: color,
}},
}

if len(n.conf.AvatarURL) != 0 {
if _, err := netUrl.Parse(n.conf.AvatarURL); err == nil {
w.AvatarURL = n.conf.AvatarURL
} else {
level.Warn(n.logger).Log("msg", "Bad avatar url", "key", key)
}
}

var payload bytes.Buffer
if err = json.NewEncoder(&payload).Encode(w); err != nil {
return false, err
Expand Down
63 changes: 63 additions & 0 deletions notify/discord/discord_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
Expand Down Expand Up @@ -168,3 +169,65 @@ func TestDiscordReadingURLFromFile(t *testing.T) {

test.AssertNotifyLeaksNoSecret(ctx, t, notifier, u.String())
}

func TestDiscord_Notify(t *testing.T) {
// Create a fake HTTP server to simulate the Discord webhook
var resp string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Read the request as a string
body, err := io.ReadAll(r.Body)
require.NoError(t, err, "reading request body failed")
// Store the request body in the response
resp = string(body)

w.WriteHeader(http.StatusOK)
}))

// Create a temporary file to simulate the WebhookURLFile
tempFile, err := os.CreateTemp("", "webhook_url")
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, os.Remove(tempFile.Name()))
})

// Write the fake webhook URL to the temp file
_, err = tempFile.WriteString(srv.URL)
require.NoError(t, err)

// Create a DiscordConfig with the WebhookURLFile set
cfg := &config.DiscordConfig{
WebhookURLFile: tempFile.Name(),
HTTPConfig: &commoncfg.HTTPClientConfig{},
Title: "Test Title",
Message: "Test Message",
Content: "Test Content",
Username: "Test Username",
AvatarURL: "http://example.com/avatar.png",
}

// Create a new Discord notifier
notifier, err := New(cfg, test.CreateTmpl(t), log.NewNopLogger())
require.NoError(t, err)

// Create a context and alerts
ctx := context.Background()
ctx = notify.WithGroupKey(ctx, "1")
alerts := []*types.Alert{
{
Alert: model.Alert{
Labels: model.LabelSet{
"lbl1": "val1",
},
StartsAt: time.Now(),
EndsAt: time.Now().Add(time.Hour),
},
},
}

// Call the Notify method
ok, err := notifier.Notify(ctx, alerts...)
require.NoError(t, err)
require.False(t, ok)

require.Equal(t, "{\"content\":\"Test Content\",\"embeds\":[{\"title\":\"Test Title\",\"description\":\"Test Message\",\"color\":10038562}],\"username\":\"Test Username\",\"avatar_url\":\"http://example.com/avatar.png\"}\n", resp)
}

0 comments on commit 540f712

Please sign in to comment.