Refactor validation for alert and monitor to return errors
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
e096217e43
commit
da5675c642
31
alert.go
31
alert.go
@ -37,13 +37,32 @@ type AlertNotice struct {
|
||||
LastCheckOutput string
|
||||
}
|
||||
|
||||
// IsValid returns a boolean indicating if the Alert has been correctly
|
||||
// configured
|
||||
func (alert Alert) IsValid() bool {
|
||||
hasAtLeastOneCommand := alert.Command != nil || alert.ShellCommand != ""
|
||||
hasAtMostOneCommand := alert.Command == nil || alert.ShellCommand == ""
|
||||
// Validate checks that the Alert is properly configured and returns errors if not
|
||||
func (alert Alert) Validate() error {
|
||||
hasCommand := len(alert.Command) > 0
|
||||
hasShellCommand := alert.ShellCommand != ""
|
||||
|
||||
return hasAtLeastOneCommand && hasAtMostOneCommand
|
||||
var err error
|
||||
|
||||
hasAtLeastOneCommand := hasCommand || hasShellCommand
|
||||
if !hasAtLeastOneCommand {
|
||||
err = errors.Join(err, fmt.Errorf(
|
||||
"%w: alert %s has no command or shell_command configured",
|
||||
ErrInvalidAlert,
|
||||
alert.Name,
|
||||
))
|
||||
}
|
||||
|
||||
hasAtMostOneCommand := !(hasCommand && hasShellCommand)
|
||||
if !hasAtMostOneCommand {
|
||||
err = errors.Join(err, fmt.Errorf(
|
||||
"%w: alert %s has both command and shell_command configured",
|
||||
ErrInvalidAlert,
|
||||
alert.Name,
|
||||
))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// BuildTemplates compiles command templates for the Alert
|
||||
|
@ -1,20 +1,24 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
m "git.iamthefij.com/iamthefij/minitor-go"
|
||||
)
|
||||
|
||||
func TestAlertIsValid(t *testing.T) {
|
||||
func TestAlertValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
alert m.Alert
|
||||
expected bool
|
||||
expected error
|
||||
name string
|
||||
}{
|
||||
{m.Alert{Command: []string{"echo", "test"}}, true, "Command only"},
|
||||
{m.Alert{ShellCommand: "echo test"}, true, "CommandShell only"},
|
||||
{m.Alert{}, false, "No commands"},
|
||||
{m.Alert{Command: []string{"echo", "test"}}, nil, "Command only"},
|
||||
{m.Alert{ShellCommand: "echo test"}, nil, "CommandShell only"},
|
||||
{m.Alert{Command: []string{"echo", "test"}, ShellCommand: "echo test"}, m.ErrInvalidAlert, "Both commands"},
|
||||
{m.Alert{}, m.ErrInvalidAlert, "No commands"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@ -23,8 +27,11 @@ func TestAlertIsValid(t *testing.T) {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actual := c.alert.IsValid()
|
||||
if actual != c.expected {
|
||||
actual := c.alert.Validate()
|
||||
hasErr := (actual != nil)
|
||||
expectErr := (c.expected != nil)
|
||||
|
||||
if hasErr != expectErr || !errors.Is(actual, c.expected) {
|
||||
t.Errorf("expected=%t actual=%t", c.expected, actual)
|
||||
}
|
||||
})
|
||||
|
@ -73,9 +73,7 @@ func (config Config) IsValid() error {
|
||||
}
|
||||
|
||||
for _, alert := range config.Alerts {
|
||||
if !alert.IsValid() {
|
||||
err = errors.Join(err, fmt.Errorf("%w: %s", ErrInvalidAlert, alert.Name))
|
||||
}
|
||||
err = errors.Join(err, alert.Validate())
|
||||
}
|
||||
|
||||
// Validate monitors
|
||||
@ -84,9 +82,7 @@ func (config Config) IsValid() error {
|
||||
}
|
||||
|
||||
for _, monitor := range config.Monitors {
|
||||
if !monitor.IsValid() {
|
||||
err = errors.Join(err, fmt.Errorf("%w: %s", ErrInvalidMonitor, monitor.Name))
|
||||
}
|
||||
err = errors.Join(err, monitor.Validate())
|
||||
|
||||
// Check that all Monitor alerts actually exist
|
||||
for _, isUp := range []bool{true, false} {
|
||||
|
49
monitor.go
49
monitor.go
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"os/exec"
|
||||
@ -65,21 +66,51 @@ func (monitor *Monitor) Init(defaultAlertAfter int, defaultAlertEvery *int, defa
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValid returns a boolean indicating if the Monitor has been correctly configured
|
||||
func (monitor Monitor) IsValid() bool {
|
||||
// TODO: Refactor and return an error containing more information on what was invalid
|
||||
// Validate checks that the Monitor is properly configured and returns errors if not
|
||||
func (monitor Monitor) Validate() error {
|
||||
hasCommand := len(monitor.Command) > 0
|
||||
hasShellCommand := monitor.ShellCommand != ""
|
||||
hasValidAlertAfter := monitor.AlertAfter > 0
|
||||
hasAlertDown := len(monitor.AlertDown) > 0
|
||||
|
||||
hasAtLeastOneCommand := hasCommand || hasShellCommand
|
||||
hasAtMostOneCommand := !(hasCommand && hasShellCommand)
|
||||
var err error
|
||||
|
||||
return hasAtLeastOneCommand &&
|
||||
hasAtMostOneCommand &&
|
||||
hasValidAlertAfter &&
|
||||
hasAlertDown
|
||||
hasAtLeastOneCommand := hasCommand || hasShellCommand
|
||||
if !hasAtLeastOneCommand {
|
||||
err = errors.Join(err, fmt.Errorf(
|
||||
"%w: monitor %s has no command or shell_command configured",
|
||||
ErrInvalidMonitor,
|
||||
monitor.Name,
|
||||
))
|
||||
}
|
||||
|
||||
hasAtMostOneCommand := !(hasCommand && hasShellCommand)
|
||||
if !hasAtMostOneCommand {
|
||||
err = errors.Join(err, fmt.Errorf(
|
||||
"%w: monitor %s has both command and shell_command configured",
|
||||
ErrInvalidMonitor,
|
||||
monitor.Name,
|
||||
))
|
||||
}
|
||||
|
||||
if !hasValidAlertAfter {
|
||||
err = errors.Join(err, fmt.Errorf(
|
||||
"%w: monitor %s has invalid alert_after value %d. Must be greater than 0",
|
||||
ErrInvalidMonitor,
|
||||
monitor.Name,
|
||||
monitor.AlertAfter,
|
||||
))
|
||||
}
|
||||
|
||||
if !hasAlertDown {
|
||||
err = errors.Join(err, fmt.Errorf(
|
||||
"%w: monitor %s has no alert_down configured. Configure one here or add a default_alert_down",
|
||||
ErrInvalidMonitor,
|
||||
monitor.Name,
|
||||
))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (monitor Monitor) LastOutput() string {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@ -8,18 +9,19 @@ import (
|
||||
m "git.iamthefij.com/iamthefij/minitor-go"
|
||||
)
|
||||
|
||||
// TestMonitorIsValid tests the Monitor.IsValid()
|
||||
func TestMonitorIsValid(t *testing.T) {
|
||||
func TestMonitorValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
monitor m.Monitor
|
||||
expected bool
|
||||
expected error
|
||||
name string
|
||||
}{
|
||||
{m.Monitor{AlertAfter: 1, Command: []string{"echo", "test"}, AlertDown: []string{"log"}}, true, "Command only"},
|
||||
{m.Monitor{AlertAfter: 1, ShellCommand: "echo test", AlertDown: []string{"log"}}, true, "CommandShell only"},
|
||||
{m.Monitor{AlertAfter: 1, Command: []string{"echo", "test"}}, false, "No AlertDown"},
|
||||
{m.Monitor{AlertAfter: 1, AlertDown: []string{"log"}}, false, "No commands"},
|
||||
{m.Monitor{AlertAfter: -1, Command: []string{"echo", "test"}, AlertDown: []string{"log"}}, false, "Invalid alert threshold, -1"},
|
||||
{m.Monitor{AlertAfter: 1, Command: []string{"echo", "test"}, AlertDown: []string{"log"}}, nil, "Command only"},
|
||||
{m.Monitor{AlertAfter: 1, ShellCommand: "echo test", AlertDown: []string{"log"}}, nil, "CommandShell only"},
|
||||
{m.Monitor{AlertAfter: 1, Command: []string{"echo", "test"}}, m.ErrInvalidMonitor, "No AlertDown"},
|
||||
{m.Monitor{AlertAfter: 1, AlertDown: []string{"log"}}, m.ErrInvalidMonitor, "No commands"},
|
||||
{m.Monitor{AlertAfter: -1, Command: []string{"echo", "test"}, AlertDown: []string{"log"}}, m.ErrInvalidMonitor, "Invalid alert threshold, -1"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@ -28,8 +30,11 @@ func TestMonitorIsValid(t *testing.T) {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
actual := c.monitor.IsValid()
|
||||
if actual != c.expected {
|
||||
actual := c.monitor.Validate()
|
||||
hasErr := (actual != nil)
|
||||
expectErr := (c.expected != nil)
|
||||
|
||||
if hasErr != expectErr || !errors.Is(actual, c.expected) {
|
||||
t.Errorf("IsValid(%v), expected=%t actual=%t", c.name, c.expected, actual)
|
||||
}
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user