diff --git a/outputs/nagios.go b/outputs/nagios.go index 2940d223..efb2629d 100644 --- a/outputs/nagios.go +++ b/outputs/nagios.go @@ -3,6 +3,7 @@ package outputs import ( "fmt" "io" + "path/filepath" "strconv" "time" @@ -28,6 +29,7 @@ func (r Nagios) Output(w io.Writer, results <-chan []resource.TestResult, perfdata = util.IsValueInList(foPerfData, outConfig.FormatOptions) verbose = util.IsValueInList(foVerbose, outConfig.FormatOptions) includeRaw := !util.IsValueInList(foExcludeRaw, outConfig.FormatOptions) + specFile := filepath.Base(outConfig.SpecFile) var startTime time.Time var endTime time.Time @@ -55,23 +57,28 @@ func (r Nagios) Output(w io.Writer, results <-chan []resource.TestResult, } duration := endTime.Sub(startTime) + return writeNagiosResult(w, specFile, testCount, failed, skipped, duration, perfdata, verbose, summary) +} + +func writeNagiosResult(w io.Writer, specFile string, testCount, failed, skipped int, duration time.Duration, perfdata, verbose bool, summary map[int]string) int { + nagiosState := "OK" if failed > 0 { - fmt.Fprintf(w, "GOSS CRITICAL - Count: %d, Failed: %d, Skipped: %d, Duration: %.3fs", testCount, failed, skipped, duration.Seconds()) - if perfdata { - fmt.Fprintf(w, "|total=%d failed=%d skipped=%d duration=%.3fs", testCount, failed, skipped, duration.Seconds()) - } - fmt.Fprint(w, "\n") - if verbose { - for i := 0; i < failed; i++ { - fmt.Fprintf(w, "%s", summary[i]) - } - } - return 2 + nagiosState = "CRITICAL" } - fmt.Fprintf(w, "GOSS OK - Count: %d, Failed: %d, Skipped: %d, Duration: %.3fs", testCount, failed, skipped, duration.Seconds()) + + fmt.Fprintf(w, "GOSS-%s %s - Count: %d, Failed: %d, Skipped: %d, Duration: %.3fs", specFile, nagiosState, testCount, failed, skipped, duration.Seconds()) if perfdata { fmt.Fprintf(w, "|total=%d failed=%d skipped=%d duration=%.3fs", testCount, failed, skipped, duration.Seconds()) } fmt.Fprint(w, "\n") - return 0 + if verbose { + for i := 0; i < failed; i++ { + fmt.Fprintf(w, "%s", summary[i]) + } + } + if failed > 0 { + return 2 + } else { + return 0 + } } diff --git a/outputs/nagios_test.go b/outputs/nagios_test.go new file mode 100644 index 00000000..183599df --- /dev/null +++ b/outputs/nagios_test.go @@ -0,0 +1,133 @@ +package outputs + +import ( + "bytes" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestWriteNagiosResult_Table(t *testing.T) { + tests := []struct { + name string + specFile string + testCount int + failed int + skipped int + duration time.Duration + perfdata bool + verbose bool + summary map[int]string + wantContains []string + wantNotContains []string + wantRet int + }{ + { + name: "ok no perf no verbose", + specFile: "goss.yaml", + testCount: 3, + failed: 0, + skipped: 0, + duration: 1500 * time.Millisecond, + perfdata: false, + verbose: false, + summary: nil, + wantContains: []string{"GOSS-goss.yaml OK", "Count: 3", "Failed: 0"}, + wantNotContains: []string{"|total=", "Fail "}, + wantRet: 0, + }, + { + name: "critical with perf", + specFile: "GossFilename.yaml", + testCount: 5, + failed: 2, + skipped: 1, + duration: 2 * time.Second, + perfdata: true, + verbose: false, + summary: nil, + wantContains: []string{"GOSS-GossFilename.yaml CRITICAL", "|total=5 failed=2 skipped=1"}, + wantNotContains: []string{"Fail "}, + wantRet: 2, + }, + { + name: "critical verbose", + specFile: "gossConfAbc.yaml", + testCount: 2, + failed: 1, + skipped: 0, + duration: 500 * time.Millisecond, + perfdata: false, + verbose: true, + summary: map[int]string{ + 0: "Fail 1 - something went wrong\n", + }, + wantContains: []string{"GOSS-gossConfAbc.yaml CRITICAL", "Fail 1 - something went wrong"}, + wantNotContains: []string{"|total="}, + wantRet: 2, + }, + { + name: "critical perf and verbose", + specFile: "gossConfFile.yaml", + testCount: 4, + failed: 2, + skipped: 1, + duration: 1250 * time.Millisecond, + perfdata: true, + verbose: true, + summary: map[int]string{ + 0: "Fail 1 - a\n", + 1: "Fail 2 - b\n", + }, + wantContains: []string{"GOSS-gossConfFile.yaml CRITICAL", "|total=4 failed=2 skipped=1", "Fail 1 - a", "Fail 2 - b"}, + wantNotContains: []string{}, + wantRet: 2, + }, + { + name: "checkNoPanic1 - missing summary text", + specFile: "gossConfFile.yaml", + testCount: 4, + failed: 2, + skipped: 1, + duration: 1250 * time.Millisecond, + perfdata: true, + verbose: true, + summary: map[int]string{}, + wantContains: []string{"GOSS-gossConfFile.yaml CRITICAL", "|total=4 failed=2 skipped=1"}, + wantNotContains: []string{}, + wantRet: 2, + }, + { + name: "checkNoPanic2 - verbose but missing", + specFile: "gossConfFile.yaml", + testCount: 4, + failed: 2, + skipped: 1, + duration: 1250 * time.Millisecond, + perfdata: false, + verbose: true, + summary: map[int]string{}, + wantContains: []string{"GOSS-gossConfFile.yaml CRITICAL", "Count: 4", "Failed: 2", "Skipped: 1"}, + wantNotContains: []string{}, + wantRet: 2, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var buf bytes.Buffer + rtn := writeNagiosResult(&buf, tt.specFile, tt.testCount, tt.failed, tt.skipped, tt.duration, tt.perfdata, tt.verbose, tt.summary) + out := buf.String() + + assert.Equal(t, tt.wantRet, rtn, "Return code mismatch") + + for _, want := range tt.wantContains { + assert.Contains(t, out, want) + } + for _, not := range tt.wantNotContains { + assert.NotContains(t, out, not) + } + }) + } +} diff --git a/util/config.go b/util/config.go index 3be5fa84..6e5532e0 100644 --- a/util/config.go +++ b/util/config.go @@ -251,6 +251,7 @@ func WithDisabledResourceTypes(t ...string) ConfigOption { type OutputConfig struct { FormatOptions []string + SpecFile string } type format string diff --git a/validate.go b/validate.go index 9e4c394c..61258365 100644 --- a/validate.go +++ b/validate.go @@ -119,6 +119,7 @@ func ValidateConfig(c *util.Config, gossConfig *GossConfig) (code int, err error format.UseStringerRepresentation = true outputConfig := util.OutputConfig{ FormatOptions: c.FormatOptions, + SpecFile: c.Spec, } sys := system.New(c.PackageManager)