Skip to content

Commit

Permalink
support loading pushover secrets from files (prometheus#3200)
Browse files Browse the repository at this point in the history
* support loading pushover secrets from files

Add the user_key_file and token_file keys to the pushover config.

/cc prometheus#2498

Signed-off-by: Simon Rozet <me@simonrozet.com>
  • Loading branch information
sr authored and hoperays committed Apr 23, 2023
1 parent f98e70d commit 1be7596
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 20 deletions.
38 changes: 23 additions & 15 deletions config/notifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,17 +666,19 @@ type PushoverConfig struct {

HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`

UserKey Secret `yaml:"user_key,omitempty" json:"user_key,omitempty"`
Token Secret `yaml:"token,omitempty" json:"token,omitempty"`
Title string `yaml:"title,omitempty" json:"title,omitempty"`
Message string `yaml:"message,omitempty" json:"message,omitempty"`
URL string `yaml:"url,omitempty" json:"url,omitempty"`
URLTitle string `yaml:"url_title,omitempty" json:"url_title,omitempty"`
Sound string `yaml:"sound,omitempty" json:"sound,omitempty"`
Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
Retry duration `yaml:"retry,omitempty" json:"retry,omitempty"`
Expire duration `yaml:"expire,omitempty" json:"expire,omitempty"`
HTML bool `yaml:"html" json:"html,omitempty"`
UserKey Secret `yaml:"user_key,omitempty" json:"user_key,omitempty"`
UserKeyFile string `yaml:"user_key_file,omitempty" json:"user_key_file,omitempty"`
Token Secret `yaml:"token,omitempty" json:"token,omitempty"`
TokenFile string `yaml:"token_file,omitempty" json:"token_file,omitempty"`
Title string `yaml:"title,omitempty" json:"title,omitempty"`
Message string `yaml:"message,omitempty" json:"message,omitempty"`
URL string `yaml:"url,omitempty" json:"url,omitempty"`
URLTitle string `yaml:"url_title,omitempty" json:"url_title,omitempty"`
Sound string `yaml:"sound,omitempty" json:"sound,omitempty"`
Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
Retry duration `yaml:"retry,omitempty" json:"retry,omitempty"`
Expire duration `yaml:"expire,omitempty" json:"expire,omitempty"`
HTML bool `yaml:"html" json:"html,omitempty"`
}

// UnmarshalYAML implements the yaml.Unmarshaler interface.
Expand All @@ -686,11 +688,17 @@ func (c *PushoverConfig) UnmarshalYAML(unmarshal func(interface{}) error) error
if err := unmarshal((*plain)(c)); err != nil {
return err
}
if c.UserKey == "" {
return fmt.Errorf("missing user key in Pushover config")
if c.UserKey == "" && c.UserKeyFile == "" {
return fmt.Errorf("one of user_key or user_key_file must be configured")
}
if c.Token == "" {
return fmt.Errorf("missing token in Pushover config")
if c.UserKey != "" && c.UserKeyFile != "" {
return fmt.Errorf("at most one of user_key & user_key_file must be configured")
}
if c.Token == "" && c.TokenFile == "" {
return fmt.Errorf("one of token or token_file must be configured")
}
if c.Token != "" && c.TokenFile != "" {
return fmt.Errorf("at most one of token & token_file must be configured")
}
return nil
}
Expand Down
41 changes: 39 additions & 2 deletions config/notifiers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,25 @@ user_key: ''
var cfg PushoverConfig
err := yaml.UnmarshalStrict([]byte(in), &cfg)

expected := "missing user key in Pushover config"
expected := "one of user_key or user_key_file must be configured"

if err == nil {
t.Fatalf("no error returned, expected:\n%v", expected)
}
if err.Error() != expected {
t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
}
}

func TestPushoverUserKeyOrUserKeyFile(t *testing.T) {
in := `
user_key: 'user key'
user_key_file: /pushover/user_key
`
var cfg PushoverConfig
err := yaml.UnmarshalStrict([]byte(in), &cfg)

expected := "at most one of user_key & user_key_file must be configured"

if err == nil {
t.Fatalf("no error returned, expected:\n%v", expected)
Expand All @@ -409,7 +427,26 @@ token: ''
var cfg PushoverConfig
err := yaml.UnmarshalStrict([]byte(in), &cfg)

expected := "missing token in Pushover config"
expected := "one of token or token_file must be configured"

if err == nil {
t.Fatalf("no error returned, expected:\n%v", expected)
}
if err.Error() != expected {
t.Errorf("\nexpected:\n%v\ngot:\n%v", expected, err.Error())
}
}

func TestPushoverTokenOrTokenFile(t *testing.T) {
in := `
token: 'pushover token'
token_file: /pushover/token
user_key: 'user key'
`
var cfg PushoverConfig
err := yaml.UnmarshalStrict([]byte(in), &cfg)

expected := "at most one of token & token_file must be configured"

if err == nil {
t.Fatalf("no error returned, expected:\n%v", expected)
Expand Down
6 changes: 5 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -862,13 +862,17 @@ Pushover notifications are sent via the [Pushover API](https://pushover.net/api)
# Whether to notify about resolved alerts.
[ send_resolved: <boolean> | default = true ]

# The recipient user's user key.
# The recipient user's key.
# user_key and user_key_file are mutually exclusive.
user_key: <secret>
user_key_file: <filepath>

# Your registered application's API token, see https://pushover.net/apps
# You can also register a token by cloning this Prometheus app:
# https://pushover.net/apps/clone/prometheus
# token and token_file are mutually exclusive.
token: <secret>
token_file: <filepath>

# Notification title.
[ title: <tmpl_string> | default = '{{ template "pushover.default.title" . }}' ]
Expand Down
28 changes: 26 additions & 2 deletions notify/pushover/pushover.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"net/http"
"net/url"
"os"
"strings"
"time"

Expand Down Expand Up @@ -83,9 +84,32 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
tmpl := notify.TmplText(n.tmpl, data, &err)
tmplHTML := notify.TmplHTML(n.tmpl, data, &err)

var (
token string
userKey string
)
if n.conf.Token != "" {
token = string(n.conf.Token)
} else {
content, err := os.ReadFile(n.conf.TokenFile)
if err != nil {
return false, fmt.Errorf("read token_file: %w", err)
}
token = string(content)
}
if n.conf.UserKey != "" {
userKey = string(n.conf.UserKey)
} else {
content, err := os.ReadFile(n.conf.UserKeyFile)
if err != nil {
return false, fmt.Errorf("read user_key_file: %w", err)
}
userKey = string(content)
}

parameters := url.Values{}
parameters.Add("token", tmpl(string(n.conf.Token)))
parameters.Add("user", tmpl(string(n.conf.UserKey)))
parameters.Add("token", tmpl(token))
parameters.Add("user", tmpl(userKey))

title, truncated := notify.TruncateInRunes(tmpl(n.conf.Title), maxTitleLenRunes)
if truncated {
Expand Down

0 comments on commit 1be7596

Please sign in to comment.