diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/check.go | 13 | ||||
| -rw-r--r-- | internal/config.go | 11 | ||||
| -rw-r--r-- | internal/dependency.go | 51 | ||||
| -rw-r--r-- | internal/run.go | 4 | ||||
| -rw-r--r-- | internal/runchecks.go | 24 |
5 files changed, 96 insertions, 7 deletions
diff --git a/internal/check.go b/internal/check.go index 8a554ee..a9efd29 100644 --- a/internal/check.go +++ b/internal/check.go @@ -8,8 +8,9 @@ import ( ) type check struct { - Plugin string - Args []string + Plugin string + Args []string + DependsOn []string `json:"DependsOn,omitempty"` } type namedCheck struct { @@ -43,6 +44,14 @@ func (c check) run(ctx context.Context, name string) checkResult { return checkResult{name, output, nagiosCode(cmd.ProcessState.ExitCode())} } +func (c check) skip(name, output string) checkResult { + return checkResult{name, output, unknown} +} + func (c namedCheck) run(ctx context.Context) checkResult { return c.check.run(ctx, c.name) } + +func (c namedCheck) skip(output string) checkResult { + return c.check.skip(c.name, output) +} diff --git a/internal/config.go b/internal/config.go index 85782cf..cb55ec8 100644 --- a/internal/config.go +++ b/internal/config.go @@ -53,3 +53,14 @@ func newConfig(configFile string) (config, error) { return config, nil } + +func (c config) sanityCheck() error { + for name, check := range c.Checks { + for _, depName := range check.DependsOn { + if _, ok := c.Checks[depName]; !ok { + return fmt.Errorf("check '%s' depends on non existant check '%s'", depName, name) + } + } + } + return nil +} diff --git a/internal/dependency.go b/internal/dependency.go new file mode 100644 index 0000000..020b4f5 --- /dev/null +++ b/internal/dependency.go @@ -0,0 +1,51 @@ +package internal + +import ( + "context" + "fmt" +) + +type dependency struct { + okMap map[string]chan struct{} + nokMap map[string]chan struct{} +} + +func newDependency(config config) dependency { + d := dependency{ + okMap: make(map[string]chan struct{}, len(config.Checks)), + nokMap: make(map[string]chan struct{}, len(config.Checks)), + } + + for name := range config.Checks { + d.okMap[name] = make(chan struct{}) + d.nokMap[name] = make(chan struct{}) + } + + return d +} + +func (d dependency) ok(name string) { + close(d.okMap[name]) +} + +func (d dependency) notOk(name string) { + close(d.nokMap[name]) +} + +// Wait for all dependant checks to be executed! +func (d dependency) wait(ctx context.Context, dependencies []string) error { + for _, dep := range dependencies { + if _, ok := d.okMap[dep]; !ok { + // We sent an error mail already via config.sanityCheck for this case. + continue + } + select { + case <-d.okMap[dep]: + case <-d.nokMap[dep]: + return fmt.Errorf("dependency '%s' is not OK!", dep) + case <-ctx.Done(): + return fmt.Errorf("waited for too long for dependency '%s': %s", dep, ctx.Err().Error()) + } + } + return nil +} diff --git a/internal/run.go b/internal/run.go index 2fd1f7c..9583a69 100644 --- a/internal/run.go +++ b/internal/run.go @@ -8,6 +8,10 @@ func Run(ctx context.Context, configFile string, renotify bool) { panic(err) } + if err := config.sanityCheck(); err != nil { + notifyError(config, err) + } + state, err := readState(config) if err != nil { notifyError(config, err) diff --git a/internal/runchecks.go b/internal/runchecks.go index 360a1b5..48a80e8 100644 --- a/internal/runchecks.go +++ b/internal/runchecks.go @@ -11,6 +11,7 @@ func runChecks(globalCtx context.Context, state state, config config) state { limiterCh := make(chan struct{}, config.CheckConcurrency) inputCh := make(chan namedCheck) outputCh := make(chan checkResult) + deps := newDependency(config) go func() { for name, check := range config.Checks { @@ -34,17 +35,30 @@ func runChecks(globalCtx context.Context, state state, config config) state { for check := range inputCh { go func(check namedCheck) { + defer inputWg.Done() + + if err := deps.wait(globalCtx, check.DependsOn); err != nil { + deps.notOk(check.name) + outputCh <- check.skip(err.Error()) + return + } + limiterCh <- struct{}{} - defer func() { - <-limiterCh - inputWg.Done() - }() + defer func() { <-limiterCh }() ctx, cancel := context.WithTimeout(globalCtx, time.Duration(config.CheckTimeoutS)*time.Second) defer cancel() - outputCh <- check.run(ctx) + checkResult := check.run(ctx) + + if checkResult.status == critical { + deps.notOk(check.name) + } else { + deps.ok(check.name) + } + + outputCh <- checkResult }(check) } |
