allow custom config per boxID, fixes #5
This commit is contained in:
parent
1bc0252b84
commit
8df4f6c753
5 changed files with 94 additions and 56 deletions
|
@ -23,21 +23,32 @@ var configHelpCmd = &cobra.Command{
|
||||||
|
|
||||||
> Example configuration:
|
> Example configuration:
|
||||||
|
|
||||||
# override default health checks:
|
healthchecks:
|
||||||
defaultHealthchecks:
|
# override default health checks for all boxes
|
||||||
notifications:
|
default:
|
||||||
transport: email
|
notifications:
|
||||||
options:
|
transport: email
|
||||||
recipients:
|
options:
|
||||||
- fridolina@example.com
|
recipients:
|
||||||
- ruth.less@example.com
|
- fridolina@example.com
|
||||||
events:
|
events:
|
||||||
- type: "measurement_age"
|
- type: "measurement_age"
|
||||||
target: "all" # all sensors
|
target: "all" # all sensors
|
||||||
threshold: "15m" # any duration
|
threshold: "15m" # any duration
|
||||||
- type: "measurement_faulty"
|
- type: "measurement_faulty"
|
||||||
target: "all"
|
target: "all"
|
||||||
threshold: ""
|
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
|
# only needed when sending notifications via email
|
||||||
email:
|
email:
|
||||||
|
@ -48,14 +59,14 @@ var configHelpCmd = &cobra.Command{
|
||||||
from: hildegunst@example.com
|
from: hildegunst@example.com
|
||||||
|
|
||||||
|
|
||||||
> possible values for defaultHealthchecks.notifications:
|
> possible values for healthchecks.*.notifications:
|
||||||
|
|
||||||
transport | options
|
transport | options
|
||||||
----------|-------------------------------------
|
----------|-------------------------------------
|
||||||
email | recipients: list of email addresses
|
email | recipients: list of email addresses
|
||||||
|
|
||||||
|
|
||||||
> possible values for defaultHealthchecks.events[]:
|
> possible values for healthchecks.*.events[]:
|
||||||
|
|
||||||
type | description
|
type | description
|
||||||
-------------------|---------------------------------------------------
|
-------------------|---------------------------------------------------
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
|
"github.com/noerw/osem_notify/core"
|
||||||
"github.com/noerw/osem_notify/utils"
|
"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
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
|
@ -34,41 +33,16 @@ func BoxIdValidator(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkAndNotify(boxIds []string) error {
|
func checkAndNotify(boxIds []string) error {
|
||||||
|
boxLocalConfig := map[string]*core.NotifyConfig{}
|
||||||
defaultNotifyConf := &core.NotifyConfig{}
|
for _, boxID := range boxIds {
|
||||||
err := viper.UnmarshalKey("defaultHealthchecks", defaultNotifyConf)
|
c, err := getNotifyConf(boxID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
boxLocalConfig[boxID] = c
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default events, when no events are given. an empty events key indicates no checks are desired
|
results, err := core.CheckBoxes(boxLocalConfig)
|
||||||
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: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
results, err := core.CheckBoxes(boxIds, defaultNotifyConf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,18 +50,18 @@ func (results BoxCheckResults) Log() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckBoxes(boxIds []string, defaultConf *NotifyConfig) (BoxCheckResults, error) {
|
func CheckBoxes(boxLocalConfs map[string]*NotifyConfig) (BoxCheckResults, error) {
|
||||||
log.Debug("Checking notifications for ", len(boxIds), " box(es)")
|
log.Debug("Checking notifications for ", len(boxLocalConfs), " box(es)")
|
||||||
|
|
||||||
results := BoxCheckResults{}
|
results := BoxCheckResults{}
|
||||||
errs := []string{}
|
errs := []string{}
|
||||||
|
|
||||||
// TODO: check boxes in parallel, capped at 5 at once
|
// 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 := log.WithField("boxId", boxId)
|
||||||
boxLogger.Info("checking box for events")
|
boxLogger.Info("checking box for events")
|
||||||
|
|
||||||
box, res, err := checkBox(boxId, defaultConf)
|
box, res, err := checkBox(boxId, localConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
boxLogger.Errorf("could not run checks on box %s: %s", boxId, err)
|
boxLogger.Errorf("could not run checks on box %s: %s", boxId, err)
|
||||||
errs = append(errs, err.Error())
|
errs = append(errs, err.Error())
|
||||||
|
|
|
@ -14,7 +14,7 @@ const (
|
||||||
eventTargetAll = "all" // if event.Target is this value, all sensors will be checked
|
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
|
name string // name that is used in config
|
||||||
toString func(result CheckResult) string // error message when check failed
|
toString func(result CheckResult) string // error message when check failed
|
||||||
checkFunc func(event NotifyEvent, sensor Sensor, context Box) (CheckResult, error)
|
checkFunc func(event NotifyEvent, sensor Sensor, context Box) (CheckResult, error)
|
||||||
|
|
Loading…
Add table
Reference in a new issue