From 5c5388d68372e92091c39117e58ccc437ac61d55 Mon Sep 17 00:00:00 2001 From: Ian Fijolek Date: Thu, 3 Oct 2019 18:16:03 -0700 Subject: [PATCH] Add some config tests Still some more to add --- config.go | 34 ++++++++++++++++++-------- config_test.go | 30 +++++++++++++++++++++++ main.go | 5 +++- test/invalid-config-missing-alerts.yml | 9 +++++++ test/invalid-config-type.yml | 1 + test/valid-config.yml | 22 +++++++++++++++++ 6 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 config_test.go create mode 100644 test/invalid-config-missing-alerts.yml create mode 100644 test/invalid-config-type.yml create mode 100644 test/valid-config.yml diff --git a/config.go b/config.go index a577437..34b870b 100644 --- a/config.go +++ b/config.go @@ -1,6 +1,7 @@ package main import ( + "errors" "gopkg.in/yaml.v2" "io/ioutil" "log" @@ -17,6 +18,12 @@ type Config struct { // IsValid checks config validity and returns true if valid func (config Config) IsValid() (isValid bool) { isValid = true + + // Validate monitors + if config.Monitors == nil || len(config.Monitors) == 0 { + log.Printf("ERROR: Invalid monitor configuration: Must provide at least one monitor") + isValid = false + } for _, monitor := range config.Monitors { if !monitor.IsValid() { log.Printf("ERROR: Invalid monitor configuration: %s", monitor.Name) @@ -24,6 +31,11 @@ func (config Config) IsValid() (isValid bool) { } } + // Validate alerts + if config.Alerts == nil || len(config.Alerts) == 0 { + log.Printf("ERROR: Invalid alert configuration: Must provide at least one alert") + isValid = false + } for _, alert := range config.Alerts { if !alert.IsValid() { log.Printf("ERROR: Invalid alert configuration: %s", alert.Name) @@ -35,38 +47,40 @@ func (config Config) IsValid() (isValid bool) { } // Init performs extra initialization on top of loading the config from file -func (config *Config) Init() { +func (config *Config) Init() (err error) { for name, alert := range config.Alerts { alert.Name = name - if err := alert.BuildTemplates(); err != nil { - panic(err) + if err = alert.BuildTemplates(); err != nil { + return } } + + return } // LoadConfig will read config from the given path and parse it -func LoadConfig(filePath string) (config Config) { +func LoadConfig(filePath string) (config Config, err error) { data, err := ioutil.ReadFile(filePath) if err != nil { - panic(err) + return } // TODO: Decide if this is better expanded here, or only when executing envExpanded := os.ExpandEnv(string(data)) err = yaml.Unmarshal([]byte(envExpanded), &config) if err != nil { - log.Fatalf("ERROR: %v", err) - panic(err) + return } log.Printf("config:\n%v\n", config) if !config.IsValid() { - panic("Cannot continue with invalid configuration") + err = errors.New("Invalid configuration") + return } // Finish initializing configuration - config.Init() + err = config.Init() - return config + return } diff --git a/config_test.go b/config_test.go new file mode 100644 index 0000000..be1bdc0 --- /dev/null +++ b/config_test.go @@ -0,0 +1,30 @@ +package main + +import ( + "log" + "testing" +) + +func TestLoadConfig(t *testing.T) { + cases := []struct { + configPath string + expectErr bool + name string + }{ + {"./test/valid-config.yml", false, "Valid config file"}, + {"./test/does-not-exist", true, "Invalid config path"}, + {"./test/invalid-config-type.yml", true, "Invalid config type for key"}, + {"./test/invalid-config-missing-alerts.yml", true, "Invalid config missing alerts"}, + } + + for _, c := range cases { + log.Printf("Testing case %s", c.name) + _, err := LoadConfig(c.configPath) + hasErr := (err != nil) + if hasErr != c.expectErr { + t.Errorf("LoadConfig(%v), expected=%v actual=%v", c.name, "Err", err) + log.Printf("Case failed: %s", c.name) + } + log.Println("-----") + } +} diff --git a/main.go b/main.go index 6ef9397..3004a74 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,10 @@ import ( ) func main() { - config := LoadConfig("config.yml") + config, err := LoadConfig("config.yml") + if err != nil { + log.Fatalf("Error loading config: %v", err) + } for { for _, monitor := range config.Monitors { diff --git a/test/invalid-config-missing-alerts.yml b/test/invalid-config-missing-alerts.yml new file mode 100644 index 0000000..1618639 --- /dev/null +++ b/test/invalid-config-missing-alerts.yml @@ -0,0 +1,9 @@ +check_interval: 1 + +monitors: + - name: Command + command: ['echo', '$PATH'] + alert_down: [ 'alert_down', 'log_shell', 'log_command' ] + # alert_every: -1 + alert_every: 0 + diff --git a/test/invalid-config-type.yml b/test/invalid-config-type.yml new file mode 100644 index 0000000..feed899 --- /dev/null +++ b/test/invalid-config-type.yml @@ -0,0 +1 @@ +check_interval: woops, I'm not an int! diff --git a/test/valid-config.yml b/test/valid-config.yml new file mode 100644 index 0000000..b7abcdf --- /dev/null +++ b/test/valid-config.yml @@ -0,0 +1,22 @@ +check_interval: 1 + +monitors: + - name: Command + command: ['echo', '$PATH'] + alert_down: [ 'log_command', 'log_shell' ] + alert_every: 0 + - name: Shell + command_shell: > + echo 'Some string with stuff'; + echo 'another line'; + echo $PATH; + exit 1 + alert_down: [ 'log_command', 'log_shell' ] + alert_after: 5 + alert_every: 0 + +alerts: + log_command: + command: [ 'echo', 'regular', '"command!!!"', "{{.MonitorName}}" ] + log_shell: + command_shell: echo "Failure on {{.MonitorName}} User is $USER"