From 8df4f6c7537bbce0a03fed0b972f2f1285234876 Mon Sep 17 00:00:00 2001 From: Norwin Roosen Date: Fri, 29 Jun 2018 20:24:02 +0200 Subject: [PATCH] allow custom config per boxID, fixes #5 --- cmd/cmd_root.go | 45 +++++++++++++++++++++++-------------- cmd/config.go | 53 ++++++++++++++++++++++++++++++++++++++++++++ cmd/shared.go | 40 ++++++--------------------------- core/checkrunner.go | 8 +++---- core/healthchecks.go | 2 +- 5 files changed, 93 insertions(+), 55 deletions(-) diff --git a/cmd/cmd_root.go b/cmd/cmd_root.go index eb88a7a..1460b14 100644 --- a/cmd/cmd_root.go +++ b/cmd/cmd_root.go @@ -23,21 +23,32 @@ var configHelpCmd = &cobra.Command{ > Example configuration: - # override default health checks: - defaultHealthchecks: - notifications: - transport: email - options: - recipients: - - fridolina@example.com - - ruth.less@example.com - events: - - type: "measurement_age" - target: "all" # all sensors - threshold: "15m" # any duration - - type: "measurement_faulty" - target: "all" - threshold: "" + healthchecks: + # override default health checks for all boxes + default: + notifications: + transport: email + options: + recipients: + - fridolina@example.com + events: + - type: "measurement_age" + target: "all" # all sensors + threshold: "15m" # any duration + - type: "measurement_faulty" + target: "all" + threshold: "" + + # override default health checks per box + 593bcd656ccf3b0011791f5a: + notifications: + options: + recipients: + - ruth.less@example.com + events: + - type: "measurement_max" + target: "593bcd656ccf3b0011791f5b" + threshold: "40" # only needed when sending notifications via email email: @@ -48,14 +59,14 @@ var configHelpCmd = &cobra.Command{ from: hildegunst@example.com -> possible values for defaultHealthchecks.notifications: +> possible values for healthchecks.*.notifications: transport | options ----------|------------------------------------- email | recipients: list of email addresses -> possible values for defaultHealthchecks.events[]: +> possible values for healthchecks.*.events[]: type | description -------------------|--------------------------------------------------- diff --git a/cmd/config.go b/cmd/config.go index 83e0b0b..ea5f95c 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -7,6 +7,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/viper" + "github.com/noerw/osem_notify/core" "github.com/noerw/osem_notify/utils" ) @@ -59,3 +60,55 @@ func validateConfig() { } } } + +func getNotifyConf(boxID string) (*core.NotifyConfig, error) { + // config used when no configuration is present at all + conf := &core.NotifyConfig{ + Events: []core.NotifyEvent{ + core.NotifyEvent{ + Type: "measurement_age", + Target: "all", + Threshold: "15m", + }, + core.NotifyEvent{ + Type: "measurement_faulty", + Target: "all", + Threshold: "", + }, + }, + } + + // override with default configuration from file + // considering the case that .events may be defined but empty + // to allow to define no events, and don't leak shorter lists into + // previous longer ones + if keyDefined("healthchecks.default.events") { + conf.Events = []core.NotifyEvent{} + } + err := viper.UnmarshalKey("healthchecks.default", conf) + if err != nil { + return nil, err + } + + // override with per box configuration from file + if keyDefined("healthchecks."+boxID+".events") { + conf.Events = []core.NotifyEvent{} + } + err = viper.UnmarshalKey("healthchecks." + boxID, conf) + if err != nil { + return nil, err + } + + return conf, nil +} + +// implement our own keyCheck, as viper.InConfig() does not work +func keyDefined(key string) bool { + allConfKeys := viper.AllKeys() + for _, k := range allConfKeys { + if k == key { + return true + } + } + return false +} diff --git a/cmd/shared.go b/cmd/shared.go index 1e86d62..a5b9505 100644 --- a/cmd/shared.go +++ b/cmd/shared.go @@ -4,7 +4,6 @@ import ( "fmt" "regexp" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -34,41 +33,16 @@ func BoxIdValidator(cmd *cobra.Command, args []string) error { } func checkAndNotify(boxIds []string) error { - - defaultNotifyConf := &core.NotifyConfig{} - err := viper.UnmarshalKey("defaultHealthchecks", defaultNotifyConf) - if err != nil { - return err - } - - // set default events, when no events are given. an empty events key indicates no checks are desired - if len(defaultNotifyConf.Events) == 0 { - allKeys := viper.AllKeys() - eventsDefined := false - for _, k := range allKeys { - if k == "defaulthealthchecks.events" { - eventsDefined = true - break - } - } - if !eventsDefined { - log.Debug("using default checks") - defaultNotifyConf.Events = []core.NotifyEvent{ - core.NotifyEvent{ - Type: "measurement_age", - Target: "all", - Threshold: "15m", - }, - core.NotifyEvent{ - Type: "measurement_faulty", - Target: "all", - Threshold: "", - }, - } + boxLocalConfig := map[string]*core.NotifyConfig{} + for _, boxID := range boxIds { + c, err := getNotifyConf(boxID) + if err != nil { + return err } + boxLocalConfig[boxID] = c } - results, err := core.CheckBoxes(boxIds, defaultNotifyConf) + results, err := core.CheckBoxes(boxLocalConfig) if err != nil { return err } diff --git a/core/checkrunner.go b/core/checkrunner.go index 5b26b26..f6db352 100644 --- a/core/checkrunner.go +++ b/core/checkrunner.go @@ -50,18 +50,18 @@ func (results BoxCheckResults) Log() { } } -func CheckBoxes(boxIds []string, defaultConf *NotifyConfig) (BoxCheckResults, error) { - log.Debug("Checking notifications for ", len(boxIds), " box(es)") +func CheckBoxes(boxLocalConfs map[string]*NotifyConfig) (BoxCheckResults, error) { + log.Debug("Checking notifications for ", len(boxLocalConfs), " box(es)") results := BoxCheckResults{} errs := []string{} // TODO: check boxes in parallel, capped at 5 at once - for _, boxId := range boxIds { + for boxId, localConf := range boxLocalConfs { boxLogger := log.WithField("boxId", boxId) boxLogger.Info("checking box for events") - box, res, err := checkBox(boxId, defaultConf) + box, res, err := checkBox(boxId, localConf) if err != nil { boxLogger.Errorf("could not run checks on box %s: %s", boxId, err) errs = append(errs, err.Error()) diff --git a/core/healthchecks.go b/core/healthchecks.go index 3981cb2..94839e5 100644 --- a/core/healthchecks.go +++ b/core/healthchecks.go @@ -14,7 +14,7 @@ const ( eventTargetAll = "all" // if event.Target is this value, all sensors will be checked ) -type checkType = struct { +type checkType struct { name string // name that is used in config toString func(result CheckResult) string // error message when check failed checkFunc func(event NotifyEvent, sensor Sensor, context Box) (CheckResult, error)