Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow hostname override for notifiers #994

Merged
merged 3 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ comma-separated list of values to the `--notifications` option
## Settings

- `--notifications-level` (env. `WATCHTOWER_NOTIFICATIONS_LEVEL`): Controls the log level which is used for the notifications. If omitted, the default log level is `info`. Possible values are: `panic`, `fatal`, `error`, `warn`, `info`, `debug` or `trace`.
- `--notifications-hostname` (env. `WATCHTOWER_NOTIFICATIONS_HOSTNAME`): Custom hostname specified in subject/title. Useful to override the operating system hostname.
- Watchtower will post a notification every time it is started. This behavior [can be changed](https://containrrr.github.io/watchtower/arguments/#without_sending_a_startup_message) with an argument.

## Available services
Expand Down
6 changes: 6 additions & 0 deletions internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ func RegisterNotificationFlags(rootCmd *cobra.Command) {
viper.GetString("WATCHTOWER_NOTIFICATIONS_LEVEL"),
"The log level used for sending notifications. Possible values: panic, fatal, error, warn, info or debug")

flags.StringP(
"notifications-hostname",
"",
viper.GetString("WATCHTOWER_NOTIFICATIONS_HOSTNAME"),
"Custom hostname for notification titles")

flags.StringP(
"notification-email-from",
"",
Expand Down
8 changes: 4 additions & 4 deletions pkg/notifications/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ func newEmailNotifier(c *cobra.Command, acceptedLogLevels []log.Level) t.Convert
return n
}

func (e *emailTypeNotifier) GetURL() (string, error) {
func (e *emailTypeNotifier) GetURL(c *cobra.Command) (string, error) {
conf := &shoutrrrSmtp.Config{
FromAddress: e.From,
FromName: "Watchtower",
ToAddresses: []string{e.To},
Port: uint16(e.Port),
Host: e.Server,
Subject: e.getSubject(),
Subject: e.getSubject(c),
Username: e.User,
Password: e.Password,
UseStartTLS: !e.tlsSkipVerify,
Expand All @@ -87,8 +87,8 @@ func (e *emailTypeNotifier) GetURL() (string, error) {
return conf.GetURL().String(), nil
}

func (e *emailTypeNotifier) getSubject() string {
subject := GetTitle()
func (e *emailTypeNotifier) getSubject(c *cobra.Command) string {
subject := GetTitle(c)

if e.SubjectTag != "" {
subject = e.SubjectTag + " " + subject
Expand Down
4 changes: 2 additions & 2 deletions pkg/notifications/gotify.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func getGotifyURL(flags *pflag.FlagSet) string {
return gotifyURL
}

func (n *gotifyTypeNotifier) GetURL() (string, error) {
func (n *gotifyTypeNotifier) GetURL(c *cobra.Command) (string, error) {
apiURL, err := url.Parse(n.gotifyURL)
if err != nil {
return "", err
Expand All @@ -77,7 +77,7 @@ func (n *gotifyTypeNotifier) GetURL() (string, error) {
Host: apiURL.Host,
Path: apiURL.Path,
DisableTLS: apiURL.Scheme == "http",
Title: GetTitle(),
Title: GetTitle(c),
Token: n.gotifyAppToken,
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/notifications/msteams.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func newMsTeamsNotifier(cmd *cobra.Command, acceptedLogLevels []log.Level) t.Con
return n
}

func (n *msTeamsTypeNotifier) GetURL() (string, error) {
func (n *msTeamsTypeNotifier) GetURL(c *cobra.Command) (string, error) {
webhookURL, err := url.Parse(n.webHookURL)
if err != nil {
return "", err
Expand All @@ -54,7 +54,7 @@ func (n *msTeamsTypeNotifier) GetURL() (string, error) {
}

config.Color = ColorHex
config.Title = GetTitle()
config.Title = GetTitle(c)

return config.GetURL().String(), nil
}
12 changes: 9 additions & 3 deletions pkg/notifications/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (n *Notifier) getNotificationTypes(cmd *cobra.Command, levels []log.Level,
continue
}

shoutrrrURL, err := legacyNotifier.GetURL()
shoutrrrURL, err := legacyNotifier.GetURL(cmd)
if err != nil {
log.Fatal("failed to create notification config:", err)
}
Expand Down Expand Up @@ -139,10 +139,16 @@ func (n *Notifier) Close() {
}

// GetTitle returns a common notification title with hostname appended
func GetTitle() (title string) {
func GetTitle(c *cobra.Command) (title string) {
title = "Watchtower updates"

if hostname, err := os.Hostname(); err == nil {
f := c.PersistentFlags()

hostname, _ := f.GetString("notifications-hostname")

if hostname != "" {
title += " on " + hostname
} else if hostname, err := os.Hostname(); err == nil {
title += " on " + hostname
}

Expand Down
20 changes: 15 additions & 5 deletions pkg/notifications/notifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,13 @@ var _ = Describe("notifications", func() {
builderFn := notifications.NewSlackNotifier

When("passing a discord url to the slack notifier", func() {
command := cmd.NewRootCommand()
flags.RegisterNotificationFlags(command)

channel := "123456789"
token := "abvsihdbau"
color := notifications.ColorInt
title := url.QueryEscape(notifications.GetTitle())
title := url.QueryEscape(notifications.GetTitle(command))
expected := fmt.Sprintf("discord://%s@%s?color=0x%x&colordebug=0x0&colorerror=0x0&colorinfo=0x0&colorwarn=0x0&splitlines=Yes&title=%s&username=watchtower", token, channel, color, title)
buildArgs := func(url string) []string {
return []string{
Expand All @@ -69,13 +72,15 @@ var _ = Describe("notifications", func() {
When("converting a slack service config into a shoutrrr url", func() {

It("should return the expected URL", func() {
command := cmd.NewRootCommand()
flags.RegisterNotificationFlags(command)

username := "containrrrbot"
tokenA := "aaa"
tokenB := "bbb"
tokenC := "ccc"
color := url.QueryEscape(notifications.ColorHex)
title := url.QueryEscape(notifications.GetTitle())
title := url.QueryEscape(notifications.GetTitle(command))

hookURL := fmt.Sprintf("https://hooks.slack.com/services/%s/%s/%s", tokenA, tokenB, tokenC)
expectedOutput := fmt.Sprintf("slack://%s@%s/%s/%s?color=%s&title=%s", username, tokenA, tokenB, tokenC, color, title)
Expand All @@ -97,9 +102,12 @@ var _ = Describe("notifications", func() {
builderFn := notifications.NewGotifyNotifier

It("should return the expected URL", func() {
command := cmd.NewRootCommand()
flags.RegisterNotificationFlags(command)

token := "aaa"
host := "shoutrrr.local"
title := url.QueryEscape(notifications.GetTitle())
title := url.QueryEscape(notifications.GetTitle(command))

expectedOutput := fmt.Sprintf("gotify://%s/%s?title=%s", host, token, title)

Expand All @@ -120,12 +128,14 @@ var _ = Describe("notifications", func() {
builderFn := notifications.NewMsTeamsNotifier

It("should return the expected URL", func() {
command := cmd.NewRootCommand()
flags.RegisterNotificationFlags(command)

tokenA := "11111111-4444-4444-8444-cccccccccccc@22222222-4444-4444-8444-cccccccccccc"
tokenB := "33333333012222222222333333333344"
tokenC := "44444444-4444-4444-8444-cccccccccccc"
color := url.QueryEscape(notifications.ColorHex)
title := url.QueryEscape(notifications.GetTitle())
title := url.QueryEscape(notifications.GetTitle(command))

hookURL := fmt.Sprintf("https://outlook.office.com/webhook/%s/IncomingWebhook/%s/%s", tokenA, tokenB, tokenC)
expectedOutput := fmt.Sprintf("teams://%s/%s/%s?color=%s&title=%s", tokenA, tokenB, tokenC, color, title)
Expand Down Expand Up @@ -215,7 +225,7 @@ func testURL(builder builderFn, args []string, expectedURL string) {
Expect(err).NotTo(HaveOccurred())

notifier := builder(command, []log.Level{})
actualURL, err := notifier.GetURL()
actualURL, err := notifier.GetURL(command)

Expect(err).NotTo(HaveOccurred())

Expand Down
6 changes: 3 additions & 3 deletions pkg/notifications/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func newSlackNotifier(c *cobra.Command, acceptedLogLevels []log.Level) t.Convert
return n
}

func (s *slackTypeNotifier) GetURL() (string, error) {
func (s *slackTypeNotifier) GetURL(c *cobra.Command) (string, error) {
trimmedURL := strings.TrimRight(s.HookURL, "/")
trimmedURL = strings.TrimLeft(trimmedURL, "https://")
parts := strings.Split(trimmedURL, "/")
Expand All @@ -57,7 +57,7 @@ func (s *slackTypeNotifier) GetURL() (string, error) {
Channel: parts[len(parts)-3],
Token: parts[len(parts)-2],
Color: ColorInt,
Title: GetTitle(),
Title: GetTitle(c),
SplitLines: true,
Username: s.Username,
}
Expand All @@ -71,7 +71,7 @@ func (s *slackTypeNotifier) GetURL() (string, error) {
BotName: s.Username,
Token: tokens,
Color: ColorHex,
Title: GetTitle(),
Title: GetTitle(c),
}

return conf.GetURL().String(), nil
Expand Down
4 changes: 3 additions & 1 deletion pkg/types/convertible_notifier.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package types

import "github.com/spf13/cobra"

// ConvertibleNotifier is a notifier capable of creating a shoutrrr URL
type ConvertibleNotifier interface {
GetURL() (string, error)
GetURL(c *cobra.Command) (string, error)
}