Skip to content
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
3 changes: 2 additions & 1 deletion docs/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ If you want to disable TLS verification for the Gotify instance, you can use eit

To send notifications via shoutrrr, the following command-line options, or their corresponding environment variables, can be set:

- `--notification-url` (env. `WATCHTOWER_NOTIFICATION_URL`): The shoutrrr service URL to be used.
- `--notification-url` (env. `WATCHTOWER_NOTIFICATION_URL`): The shoutrrr service URL to be used. This option can also reference a file, in which case the contents of the file are used.


Go to [containrrr.dev/shoutrrr/v0.5/services/overview](https://containrrr.dev/shoutrrr/v0.5/services/overview) to
learn more about the different service URLs you can use. You can define multiple services by space separating the
Expand Down
31 changes: 28 additions & 3 deletions internal/flags/flags.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package flags

import (
"bufio"
"errors"
"io/ioutil"
"os"
Expand Down Expand Up @@ -444,6 +445,7 @@ func GetSecretsFromFiles(rootCmd *cobra.Command) {
"notification-slack-hook-url",
"notification-msteams-hook",
"notification-gotify-token",
"notification-url",
}
for _, secret := range secrets {
getSecretFromFile(flags, secret)
Expand All @@ -452,10 +454,33 @@ func GetSecretsFromFiles(rootCmd *cobra.Command) {

// getSecretFromFile will check if the flag contains a reference to a file; if it does, replaces the value of the flag with the contents of the file.
func getSecretFromFile(flags *pflag.FlagSet, secret string) {
value, err := flags.GetString(secret)
if err != nil {
log.Error(err)
flag := flags.Lookup(secret)
if sliceValue, ok := flag.Value.(pflag.SliceValue); ok {
oldValues := sliceValue.GetSlice()
values := make([]string, 0, len(oldValues))
for _, value := range oldValues {
if value != "" && isFile(value) {
file, err := os.Open(value)
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if line == "" {
continue
}
values = append(values, line)
}
} else {
values = append(values, value)
}
}
sliceValue.Replace(values)
return
}

value := flag.Value.String()
if value != "" && isFile(value) {
file, err := ioutil.ReadFile(value)
if err != nil {
Expand Down
30 changes: 27 additions & 3 deletions internal/flags/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func TestGetSecretsFromFilesWithString(t *testing.T) {

err := os.Setenv("WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD", value)
require.NoError(t, err)
defer os.Unsetenv("WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD")

testGetSecretsFromFiles(t, "notification-email-server-password", value)
}
Expand All @@ -69,17 +70,40 @@ func TestGetSecretsFromFilesWithFile(t *testing.T) {

err = os.Setenv("WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD", file.Name())
require.NoError(t, err)
defer os.Unsetenv("WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD")

testGetSecretsFromFiles(t, "notification-email-server-password", value)
}

func testGetSecretsFromFiles(t *testing.T, flagName string, expected string) {
func TestGetSliceSecretsFromFiles(t *testing.T) {
values := []string{"entry2", "", "entry3"}

// Create the temporary file which will contain a secret.
file, err := ioutil.TempFile(os.TempDir(), "watchtower-")
require.NoError(t, err)
defer os.Remove(file.Name()) // Make sure to remove the temporary file later.

// Write the secret to the temporary file.
for _, value := range values {
_, err = file.WriteString("\n" + value)
require.NoError(t, err)
}
file.Close()

testGetSecretsFromFiles(t, "notification-url", `[entry1,entry2,entry3]`,
`--notification-url`, "entry1",
`--notification-url`, file.Name())
}

func testGetSecretsFromFiles(t *testing.T, flagName string, expected string, args ...string) {
cmd := new(cobra.Command)
SetDefaults()
RegisterNotificationFlags(cmd)
require.NoError(t, cmd.ParseFlags(args))
GetSecretsFromFiles(cmd)
value, err := cmd.PersistentFlags().GetString(flagName)
require.NoError(t, err)
flag := cmd.PersistentFlags().Lookup(flagName)
require.NotNil(t, flag)
value := flag.Value.String()

assert.Equal(t, expected, value)
}
Expand Down