diff --git a/pkg/notifications/email.go b/pkg/notifications/email.go index 6a61dd1..2b1b85a 100644 --- a/pkg/notifications/email.go +++ b/pkg/notifications/email.go @@ -82,6 +82,10 @@ func (e *emailTypeNotifier) GetURL(c *cobra.Command) (string, error) { return conf.GetURL().String(), nil } +func (e *emailTypeNotifier) GetDelay() time.Duration { + return e.delay +} + func (e *emailTypeNotifier) getSubject(c *cobra.Command) string { subject := GetTitle(c) diff --git a/pkg/notifications/notifier.go b/pkg/notifications/notifier.go index 7c999d0..5bfa08c 100644 --- a/pkg/notifications/notifier.go +++ b/pkg/notifications/notifier.go @@ -1,11 +1,13 @@ package notifications import ( + "os" + "time" + ty "github.com/containrrr/watchtower/pkg/types" "github.com/johntdyer/slackrus" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "os" ) // NewNotifier creates and returns a new Notifier, using global configuration. @@ -28,14 +30,14 @@ func NewNotifier(c *cobra.Command) ty.Notifier { tplString, _ := f.GetString("notification-template") urls, _ := f.GetStringArray("notification-url") - urls = AppendLegacyUrls(urls, c) + urls, delay := AppendLegacyUrls(urls, c) title := GetTitle(c) - return newShoutrrrNotifier(tplString, acceptedLogLevels, !reportTemplate, title, urls...) + return newShoutrrrNotifier(tplString, acceptedLogLevels, !reportTemplate, title, delay, urls...) } // AppendLegacyUrls creates shoutrrr equivalent URLs from legacy notification flags -func AppendLegacyUrls(urls []string, cmd *cobra.Command) []string { +func AppendLegacyUrls(urls []string, cmd *cobra.Command) ([]string, time.Duration) { // Parse types and create notifiers. types, err := cmd.Flags().GetStringSlice("notifications") @@ -43,6 +45,8 @@ func AppendLegacyUrls(urls []string, cmd *cobra.Command) []string { log.WithError(err).Fatal("could not read notifications argument") } + delay := time.Duration(0) + for _, t := range types { var legacyNotifier ty.ConvertibleNotifier @@ -71,9 +75,13 @@ func AppendLegacyUrls(urls []string, cmd *cobra.Command) []string { } urls = append(urls, shoutrrrURL) + if delayNotifier, ok := legacyNotifier.(ty.DelayNotifier); ok { + delay = delayNotifier.GetDelay() + } + log.WithField("URL", shoutrrrURL).Trace("created Shoutrrr URL from legacy notifier") } - return urls + return urls, delay } // GetTitle returns a common notification title with hostname appended diff --git a/pkg/notifications/notifier_test.go b/pkg/notifications/notifier_test.go index 71bfea3..05d6d56 100644 --- a/pkg/notifications/notifier_test.go +++ b/pkg/notifications/notifier_test.go @@ -241,7 +241,7 @@ func testURL(args []string, expectedURL string) { err := command.ParseFlags(args) Expect(err).NotTo(HaveOccurred()) - urls := notifications.AppendLegacyUrls([]string{}, command) + urls, _ := notifications.AppendLegacyUrls([]string{}, command) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/notifications/shoutrrr.go b/pkg/notifications/shoutrrr.go index 1611a04..e41ed92 100644 --- a/pkg/notifications/shoutrrr.go +++ b/pkg/notifications/shoutrrr.go @@ -5,6 +5,7 @@ import ( stdlog "log" "strings" "text/template" + "time" "github.com/containrrr/shoutrrr" "github.com/containrrr/shoutrrr/pkg/types" @@ -77,14 +78,14 @@ func (n *shoutrrrTypeNotifier) GetNames() []string { return names } -func newShoutrrrNotifier(tplString string, acceptedLogLevels []log.Level, legacy bool, title string, urls ...string) t.Notifier { +func newShoutrrrNotifier(tplString string, acceptedLogLevels []log.Level, legacy bool, title string, delay time.Duration, urls ...string) t.Notifier { notifier := createNotifier(urls, acceptedLogLevels, tplString, legacy) notifier.params = &types.Params{"title": title} log.AddHook(notifier) // Do the sending in a separate goroutine so we don't block the main process. - go sendNotifications(notifier) + go sendNotifications(notifier, delay) return notifier } @@ -112,8 +113,9 @@ func createNotifier(urls []string, levels []log.Level, tplString string, legacy } } -func sendNotifications(n *shoutrrrTypeNotifier) { +func sendNotifications(n *shoutrrrTypeNotifier, delay time.Duration) { for msg := range n.messages { + time.Sleep(delay) errs := n.Router.Send(msg, n.params) for i, err := range errs { diff --git a/pkg/notifications/shoutrrr_test.go b/pkg/notifications/shoutrrr_test.go index 1b4ebab..6e67b6f 100644 --- a/pkg/notifications/shoutrrr_test.go +++ b/pkg/notifications/shoutrrr_test.go @@ -1,6 +1,8 @@ package notifications import ( + "time" + "github.com/containrrr/shoutrrr/pkg/types" "github.com/containrrr/watchtower/internal/actions/mocks" "github.com/containrrr/watchtower/internal/flags" @@ -212,7 +214,7 @@ Turns out everything is on fire When("batching notifications", func() { When("no messages are queued", func() { It("should not send any notification", func() { - shoutrrr := newShoutrrrNotifier("", allButTrace, true, "", "logger://") + shoutrrr := newShoutrrrNotifier("", allButTrace, true, "", time.Duration(0), "logger://") shoutrrr.StartNotification() shoutrrr.SendNotification(nil) Consistently(logBuffer).ShouldNot(gbytes.Say(`Shoutrrr:`)) @@ -220,7 +222,7 @@ Turns out everything is on fire }) When("at least one message is queued", func() { It("should send a notification", func() { - shoutrrr := newShoutrrrNotifier("", allButTrace, true, "", "logger://") + shoutrrr := newShoutrrrNotifier("", allButTrace, true, "", time.Duration(0), "logger://") shoutrrr.StartNotification() logrus.Info("This log message is sponsored by ContainrrrVPN") shoutrrr.SendNotification(nil) @@ -282,7 +284,7 @@ func sendNotificationsWithBlockingRouter(legacy bool) (*shoutrrrTypeNotifier, *b Message: "foo bar", } - go sendNotifications(shoutrrr) + go sendNotifications(shoutrrr, time.Duration(0)) shoutrrr.StartNotification() _ = shoutrrr.Fire(entry) diff --git a/pkg/types/convertible_notifier.go b/pkg/types/convertible_notifier.go index 87f8659..90f0078 100644 --- a/pkg/types/convertible_notifier.go +++ b/pkg/types/convertible_notifier.go @@ -1,8 +1,16 @@ package types -import "github.com/spf13/cobra" +import ( + "github.com/spf13/cobra" + "time" +) // ConvertibleNotifier is a notifier capable of creating a shoutrrr URL type ConvertibleNotifier interface { GetURL(c *cobra.Command) (string, error) } + +// DelayNotifier is a notifier that might need to be delayed before sending notifications +type DelayNotifier interface { + GetDelay() time.Duration +} \ No newline at end of file