Skip to content

Commit

Permalink
Channel default value by changing default logic
Browse files Browse the repository at this point in the history
In a nutshell, this allows omitting key value pairs from the
configuration JSON given to Plugin.SetConfig, falling back to default
values specified in struct tags.

To avoid storing each default value twice, it's location was moved up to
a "default" struct tag. By utilizing the already included defaults
library and adding a small wrapper for plugin.Info, those defaults are
now being set to the plugin.ConfigAttributes at runtime.

Tests for this new wrapper function, plugin.NewInfo, and for one channel
plugin were written. Furthermore, lots of lines have changed their
indentation level. Thus, the diff looks greater and scarier as it is.

Closes #205.
  • Loading branch information
oxzi committed May 31, 2024
1 parent 17a0abe commit 7ff9196
Show file tree
Hide file tree
Showing 6 changed files with 385 additions and 172 deletions.
148 changes: 75 additions & 73 deletions cmd/channel/email/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
"github.com/creasty/defaults"
"github.com/emersion/go-sasl"
"github.com/emersion/go-smtp"
"github.com/google/uuid"
Expand All @@ -26,7 +27,7 @@ type Email struct {
Host string `json:"host"`
Port string `json:"port"`
SenderName string `json:"sender_name"`
SenderMail string `json:"sender_mail"`
SenderMail string `json:"sender_mail" default:"[email protected]"`
User string `json:"user"`
Password string `json:"password"`
Encryption string `json:"encryption"`
Expand Down Expand Up @@ -95,7 +96,12 @@ func (ch *Email) Send(reversePath string, recipients []string, msg []byte) error
}

func (ch *Email) SetConfig(jsonStr json.RawMessage) error {
err := json.Unmarshal(jsonStr, ch)
err := defaults.Set(ch)
if err != nil {
return err
}

err = json.Unmarshal(jsonStr, ch)
if err != nil {
return fmt.Errorf("failed to load config: %s %w", jsonStr, err)
}
Expand All @@ -108,87 +114,83 @@ func (ch *Email) SetConfig(jsonStr json.RawMessage) error {
}

func (ch *Email) GetInfo() *plugin.Info {
elements := []*plugin.ConfigOption{
{
Name: "sender_name",
Type: "string",
Label: map[string]string{
"en_US": "Sender Name",
"de_DE": "Absendername",
},
},
{
Name: "sender_mail",
Type: "string",
Label: map[string]string{
"en_US": "Sender Address",
"de_DE": "Absenderadresse",
info, err := plugin.NewInfo(
&Email{},
"Email",
internal.Version.Version,
"Icinga GmbH",
[]*plugin.ConfigOption{
{
Name: "host",
Type: "string",
Required: true,
Label: map[string]string{
"en_US": "SMTP Host",
"de_DE": "SMTP Host",
},
},
Default: "[email protected]",
},
{
Name: "host",
Type: "string",
Required: true,
Label: map[string]string{
"en_US": "SMTP Host",
"de_DE": "SMTP Host",
{
Name: "port",
Type: "number",
Required: true,
Label: map[string]string{
"en_US": "SMTP Port",
"de_DE": "SMTP Port",
},
Min: types.Int{NullInt64: sql.NullInt64{Int64: 1, Valid: true}},
Max: types.Int{NullInt64: sql.NullInt64{Int64: 65535, Valid: true}},
},
},
{
Name: "port",
Type: "number",
Required: true,
Label: map[string]string{
"en_US": "SMTP Port",
"de_DE": "SMTP Port",
{
Name: "sender_name",
Type: "string",
Label: map[string]string{
"en_US": "Sender Name",
"de_DE": "Absendername",
},
},
Min: types.Int{NullInt64: sql.NullInt64{Int64: 1, Valid: true}},
Max: types.Int{NullInt64: sql.NullInt64{Int64: 65535, Valid: true}},
},
{
Name: "user",
Type: "string",
Label: map[string]string{
"en_US": "SMTP User",
"de_DE": "SMTP Benutzer",
{
Name: "sender_mail",
Type: "string",
Label: map[string]string{
"en_US": "Sender Address",
"de_DE": "Absenderadresse",
},
},
},
{
Name: "password",
Type: "secret",
Label: map[string]string{
"en_US": "SMTP Password",
"de_DE": "SMTP Passwort",
{
Name: "user",
Type: "string",
Label: map[string]string{
"en_US": "SMTP User",
"de_DE": "SMTP Benutzer",
},
},
},
{
Name: "encryption",
Type: "option",
Required: true,
Label: map[string]string{
"en_US": "SMTP Transport Encryption",
"de_DE": "SMTP Transportverschlüsselung",
{
Name: "password",
Type: "secret",
Label: map[string]string{
"en_US": "SMTP Password",
"de_DE": "SMTP Passwort",
},
},
Options: map[string]string{
EncryptionNone: "None",
EncryptionStartTLS: "STARTTLS",
EncryptionTLS: "TLS",
{
Name: "encryption",
Type: "option",
Required: true,
Label: map[string]string{
"en_US": "SMTP Transport Encryption",
"de_DE": "SMTP Transportverschlüsselung",
},
Options: map[string]string{
EncryptionNone: "None",
EncryptionStartTLS: "STARTTLS",
EncryptionTLS: "TLS",
},
},
},
}

configAttrs, err := json.Marshal(elements)
})
if err != nil {
panic(err)
}

return &plugin.Info{
Name: "Email",
Version: internal.Version.Version,
Author: "Icinga GmbH",
ConfigAttributes: configAttrs,
}
return info
}

func (ch *Email) GetServer() string {
Expand Down
62 changes: 62 additions & 0 deletions cmd/channel/email/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package main

import (
"encoding/json"
"github.com/stretchr/testify/assert"
"testing"
)

func TestEmail_SetConfig(t *testing.T) {
tests := []struct {
name string
jsonMsg string
want *Email
wantErr bool
}{
{
name: "empty-string",
jsonMsg: ``,
wantErr: true,
},
{
name: "empty-json-obj",
jsonMsg: `{}`,
want: &Email{SenderMail: "[email protected]"},
},
{
name: "sender-mail-empty-val",
jsonMsg: `{"sender_mail": ""}`,
want: &Email{SenderMail: ""},
},
{
name: "example",
jsonMsg: `{"sender_name":"icinga","sender_mail":"[email protected]","host":"smtp.example.com","port":"25","encryption":"none"}`,
want: &Email{
Host: "smtp.example.com",
Port: "25",
SenderName: "icinga",
SenderMail: "[email protected]",
User: "",
Password: "",
Encryption: "none",
},
},
{
name: "user-but-missing-pass",
jsonMsg: `{"user": "foo"}`,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
email := &Email{}
err := email.SetConfig(json.RawMessage(tt.jsonMsg))
assert.Equal(t, tt.wantErr, err != nil, "SetConfig() error = %v, wantErr = %t", err, tt.wantErr)
if err != nil {
return
}

assert.Equal(t, tt.want, email, "Email differs")
})
}
}
74 changes: 38 additions & 36 deletions cmd/channel/rocketchat/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/creasty/defaults"
"github.com/icinga/icinga-notifications/internal"
"github.com/icinga/icinga-notifications/pkg/plugin"
"net/http"
Expand Down Expand Up @@ -77,50 +78,51 @@ func (ch *RocketChat) SendNotification(req *plugin.NotificationRequest) error {
}

func (ch *RocketChat) SetConfig(jsonStr json.RawMessage) error {
err := defaults.Set(ch)
if err != nil {
return err
}

return json.Unmarshal(jsonStr, ch)
}

func (ch *RocketChat) GetInfo() *plugin.Info {

elements := []*plugin.ConfigOption{
{
Name: "url",
Type: "string",
Label: map[string]string{
"en_US": "Rocket.Chat URL",
"de_DE": "Rocket.Chat URL",
info, err := plugin.NewInfo(
&RocketChat{},
"Rocket.Chat",
internal.Version.Version,
"Icinga GmbH",
[]*plugin.ConfigOption{
{
Name: "url",
Type: "string",
Label: map[string]string{
"en_US": "Rocket.Chat URL",
"de_DE": "Rocket.Chat URL",
},
Required: true,
},
Required: true,
},
{
Name: "user_id",
Type: "string",
Label: map[string]string{
"en_US": "User ID",
"de_DE": "Benutzer ID",
{
Name: "user_id",
Type: "string",
Label: map[string]string{
"en_US": "User ID",
"de_DE": "Benutzer ID",
},
Required: true,
},
Required: true,
},
{
Name: "token",
Type: "secret",
Label: map[string]string{
"en_US": "Personal Access Token",
"de_DE": "Persönliches Zugangstoken",
{
Name: "token",
Type: "secret",
Label: map[string]string{
"en_US": "Personal Access Token",
"de_DE": "Persönliches Zugangstoken",
},
Required: true,
},
Required: true,
},
}

configAttrs, err := json.Marshal(elements)
})
if err != nil {
panic(err)
}

return &plugin.Info{
Name: "Rocket.Chat",
Version: internal.Version.Version,
Author: "Icinga GmbH",
ConfigAttributes: configAttrs,
}
return info
}
Loading

0 comments on commit 7ff9196

Please sign in to comment.