From eefbcd54660db5686b5469b3a0d21f82b97ab3de Mon Sep 17 00:00:00 2001 From: Tommi2Day Date: Tue, 16 Jan 2024 18:26:48 +0100 Subject: [PATCH 1/2] validate range return value in EvaluateThreshold fixes #233 --- nagios.go | 3 +++ range.go | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/nagios.go b/nagios.go index b4741af..dce167c 100644 --- a/nagios.go +++ b/nagios.go @@ -96,6 +96,9 @@ var ( // metric is not in a supported format. ErrInvalidPerformanceDataFormat = errors.New("invalid performance data format") + // ErrInvalidRangeThreshold indicates that a given range threshold is not in a supported format. + ErrInvalidRangeThreshold = errors.New("invalid range threshold") + // TODO: Should we use field-specific errors or is the more general // ErrInvalidPerformanceDataFormat "good enough" ? Wrapped versions of // that error will likely already indicate which field is a problem, but diff --git a/range.go b/range.go index 845fb49..10f0710 100644 --- a/range.go +++ b/range.go @@ -9,6 +9,7 @@ package nagios import ( + "fmt" "regexp" "strconv" "strings" @@ -149,6 +150,11 @@ func (p *Plugin) EvaluateThreshold(perfData ...PerformanceData) error { if perfData[i].Crit != "" { CriticalThresholdObject := ParseRangeString(perfData[i].Crit) + if CriticalThresholdObject == nil { + err := fmt.Errorf("failed to parse critical range string %s: %w ", perfData[i].Crit, ErrInvalidRangeThreshold) + p.ExitStatusCode = StateUNKNOWNExitCode + return err + } if CriticalThresholdObject.CheckRange(perfData[i].Value) { p.ExitStatusCode = StateCRITICALExitCode @@ -158,6 +164,11 @@ func (p *Plugin) EvaluateThreshold(perfData ...PerformanceData) error { if perfData[i].Warn != "" { warningThresholdObject := ParseRangeString(perfData[i].Warn) + if warningThresholdObject == nil { + err := fmt.Errorf("failed to parse warning range string %s: %w ", perfData[i].Warn, ErrInvalidRangeThreshold) + p.ExitStatusCode = StateUNKNOWNExitCode + return err + } if warningThresholdObject.CheckRange(perfData[i].Value) { p.ExitStatusCode = StateWARNINGExitCode From b8a299bda2b604b73ec6d348ac55157d99e84cd0 Mon Sep 17 00:00:00 2001 From: Tommi2Day Date: Tue, 16 Jan 2024 18:44:08 +0100 Subject: [PATCH 2/2] add checks testing invalid critical and warning range --- range_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/range_test.go b/range_test.go index a824bc3..ff9b0bd 100644 --- a/range_test.go +++ b/range_test.go @@ -188,6 +188,25 @@ func TestParseRange(t *testing.T) { assert.Equal(t, StateCRITICALExitCode, plugin.ExitStatusCode) }) + t.Run("Plugin should return exit code Unknown when critical range is invalid", func(t *testing.T) { + var plugin = Plugin{ + ExitStatusCode: StateOKExitCode, + } + plugin.ServiceOutput = pluginServiceOutput + + perfdata := PerformanceData{ + Label: "perfdata label", + Value: "41.0", + UnitOfMeasurement: "C", + Warn: "5:30", + Crit: "0:<=20", // invalid range as critical lower than warning + } + assert.NoError(t, plugin.AddPerfData(false, perfdata)) + assert.Error(t, plugin.EvaluateThreshold(perfdata)) + + assert.Equal(t, StateUNKNOWNExitCode, plugin.ExitStatusCode) + }) + t.Run("Plugin should return exit code CRITICAL when value is within warning range", func(t *testing.T) { var plugin = Plugin{ ExitStatusCode: StateOKExitCode, @@ -206,4 +225,23 @@ func TestParseRange(t *testing.T) { assert.Equal(t, StateCRITICALExitCode, plugin.ExitStatusCode) }) + + t.Run("Plugin should return exit code UNKNOWN and error when warning range is invalid", func(t *testing.T) { + var plugin = Plugin{ + ExitStatusCode: StateOKExitCode, + } + plugin.ServiceOutput = pluginServiceOutput + + perfdata := PerformanceData{ + Label: "perfdata label", + Value: "-1.0", + UnitOfMeasurement: "C", + Warn: "x20", // invalid range value + Crit: "", + } + assert.NoError(t, plugin.AddPerfData(false, perfdata)) + assert.Error(t, plugin.EvaluateThreshold(perfdata)) + + assert.Equal(t, StateUNKNOWNExitCode, plugin.ExitStatusCode) + }) }