Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add verbose and extended-perfdata flags #274

Merged
merged 5 commits into from May 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions cmd/goss/goss.go
Expand Up @@ -49,6 +49,11 @@ func main() {
Usage: fmt.Sprintf("Format to output in, valid options: %s", outputs.Outputers()),
EnvVar: "GOSS_FMT",
},
cli.StringSliceFlag{
Name: "format-options, o",
Usage: fmt.Sprintf("Extra options passed to the formatter, valid options: %s", outputs.FormatOptions()),
EnvVar: "GOSS_FMT_OPTIONS",
},
cli.BoolFlag{
Name: "color",
Usage: "Force color on",
Expand Down Expand Up @@ -94,6 +99,11 @@ func main() {
Usage: fmt.Sprintf("Format to output in, valid options: %s", outputs.Outputers()),
EnvVar: "GOSS_FMT",
},
cli.StringSliceFlag{
Name: "format-options, o",
Usage: fmt.Sprintf("Extra options passed to the formatter, valid options: %s", outputs.FormatOptions()),
EnvVar: "GOSS_FMT_OPTIONS",
},
cli.DurationFlag{
Name: "cache,c",
Usage: "Time to cache the results",
Expand Down
12 changes: 9 additions & 3 deletions docs/manual.md
Expand Up @@ -282,10 +282,12 @@ $ curl localhost:8080/healthz
* `json_oneline` - Same as json, but oneliner
* `junit`
* `nagios` - Nagios/Sensu compatible output /w exit code 2 for failures.
* `nagios_verbose` - Nagios output with verbose failure output.
* `rspecish` **(default)** - Similar to rspec output
* `tap`
* `silent` - No output. Avoids exposing system information (e.g. when serving tests as a healthcheck endpoint).
* `--format-options`, `-o` (output format option)
* `perfdata` - Outputs Nagios "performance data". Applies to `nagios` output.
* `verbose` - Gives verbose output. Applies to `nagios` output.
* `--max-concurrent` - Max number of tests to run concurrently
* `--no-color` - Disable color
* `--color` - Force enable color
Expand Down Expand Up @@ -313,9 +315,13 @@ $ goss render | ssh remote-host 'goss -g - validate'

Total Duration: 0.002s
Count: 6, Failed: 0, Skipped: 0
```


$ goss validate --format nagios -o verbose -o perfdata
GOSS CRITICAL - Count: 76, Failed: 1, Skipped: 0, Duration: 1.009s|total=76 failed=1 skipped=0 duration=1.009s
Fail 1 - DNS: localhost: addrs: doesn't match, expect: [["127.0.0.1","::1"]] found: [["127.0.0.1"]]
$ echo $?
2
```

## Important note about goss file format
It is important to note that both YAML and JSON are formats that describe a nested data structure.
Expand Down
7 changes: 5 additions & 2 deletions outputs/documentation.go
Expand Up @@ -6,11 +6,14 @@ import (
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
)

type Documentation struct{}

func (r Documentation) Output(w io.Writer, results <-chan []resource.TestResult, startTime time.Time) (exitCode int) {
func (r Documentation) Output(w io.Writer, results <-chan []resource.TestResult,
startTime time.Time, outConfig util.OutputConfig) (exitCode int) {

testCount := 0
var failedOrSkipped [][]resource.TestResult
var skipped, failed int
Expand Down Expand Up @@ -52,5 +55,5 @@ func (r Documentation) Output(w io.Writer, results <-chan []resource.TestResult,
}

func init() {
RegisterOutputer("documentation", &Documentation{})
RegisterOutputer("documentation", &Documentation{}, []string{})
}
7 changes: 5 additions & 2 deletions outputs/json.go
Expand Up @@ -7,12 +7,15 @@ import (
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
"github.com/fatih/color"
)

type Json struct{}

func (r Json) Output(w io.Writer, results <-chan []resource.TestResult, startTime time.Time) (exitCode int) {
func (r Json) Output(w io.Writer, results <-chan []resource.TestResult,
startTime time.Time, outConfig util.OutputConfig) (exitCode int) {

color.NoColor = true
testCount := 0
failed := 0
Expand Down Expand Up @@ -52,7 +55,7 @@ func (r Json) Output(w io.Writer, results <-chan []resource.TestResult, startTim
}

func init() {
RegisterOutputer("json", &Json{})
RegisterOutputer("json", &Json{}, []string{})
}

func struct2map(i interface{}) map[string]interface{} {
Expand Down
7 changes: 5 additions & 2 deletions outputs/json_oneline.go
Expand Up @@ -7,12 +7,15 @@ import (
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
"github.com/fatih/color"
)

type JsonOneline struct{}

func (r JsonOneline) Output(w io.Writer, results <-chan []resource.TestResult, startTime time.Time) (exitCode int) {
func (r JsonOneline) Output(w io.Writer, results <-chan []resource.TestResult,
startTime time.Time, outConfig util.OutputConfig) (exitCode int) {

color.NoColor = true
testCount := 0
failed := 0
Expand Down Expand Up @@ -52,5 +55,5 @@ func (r JsonOneline) Output(w io.Writer, results <-chan []resource.TestResult, s
}

func init() {
RegisterOutputer("json_oneline", &JsonOneline{})
RegisterOutputer("json_oneline", &JsonOneline{}, []string{})
}
7 changes: 5 additions & 2 deletions outputs/junit.go
Expand Up @@ -9,12 +9,15 @@ import (
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
"github.com/fatih/color"
)

type JUnit struct{}

func (r JUnit) Output(w io.Writer, results <-chan []resource.TestResult, startTime time.Time) (exitCode int) {
func (r JUnit) Output(w io.Writer, results <-chan []resource.TestResult,
startTime time.Time, outConfig util.OutputConfig) (exitCode int) {

color.NoColor = true
var testCount, failed, skipped int

Expand Down Expand Up @@ -75,7 +78,7 @@ func (r JUnit) Output(w io.Writer, results <-chan []resource.TestResult, startTi
}

func init() {
RegisterOutputer("junit", &JUnit{})
RegisterOutputer("junit", &JUnit{}, []string{})
}

func escapeString(str string) string {
Expand Down
36 changes: 32 additions & 4 deletions outputs/nagios.go
Expand Up @@ -3,19 +3,34 @@ package outputs
import (
"fmt"
"io"
"strconv"
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
)

type Nagios struct{}

func (r Nagios) Output(w io.Writer, results <-chan []resource.TestResult, startTime time.Time) (exitCode int) {
func (r Nagios) Output(w io.Writer, results <-chan []resource.TestResult,
startTime time.Time, outConfig util.OutputConfig) (exitCode int) {

var testCount, failed, skipped int

var perfdata, verbose bool
perfdata = util.IsValueInList("perfdata", outConfig.FormatOptions)
verbose = util.IsValueInList("verbose", outConfig.FormatOptions)

var summary map[int]string
summary = make(map[int]string)

for resultGroup := range results {
for _, testResult := range resultGroup {
switch testResult.Result {
case resource.FAIL:
if util.IsValueInList("verbose", outConfig.FormatOptions) {
summary[failed] = "Fail " + strconv.Itoa(failed+1) + " - " + humanizeResult2(testResult) + "\n"
}
failed++
case resource.SKIP:
skipped++
Expand All @@ -26,13 +41,26 @@ func (r Nagios) Output(w io.Writer, results <-chan []resource.TestResult, startT

duration := time.Since(startTime)
if failed > 0 {
fmt.Fprintf(w, "GOSS CRITICAL - Count: %d, Failed: %d, Skipped: %d, Duration: %.3fs\n", testCount, failed, skipped, duration.Seconds())
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
}
fmt.Fprintf(w, "GOSS OK - Count: %d, Failed: %d, Skipped: %d, Duration: %.3fs\n", testCount, failed, skipped, duration.Seconds())
fmt.Fprintf(w, "GOSS OK - 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")
return 0
}

func init() {
RegisterOutputer("nagios", &Nagios{})
RegisterOutputer("nagios", &Nagios{}, []string{"perfdata", "verbose"})
}
47 changes: 0 additions & 47 deletions outputs/nagios_verbose.go

This file was deleted.

26 changes: 22 additions & 4 deletions outputs/outputs.go
Expand Up @@ -10,11 +10,12 @@ import (
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
"github.com/fatih/color"
)

type Outputer interface {
Output(io.Writer, <-chan []resource.TestResult, time.Time) int
Output(io.Writer, <-chan []resource.TestResult, time.Time, util.OutputConfig) int
}

var green = color.New(color.FgGreen).SprintfFunc()
Expand Down Expand Up @@ -78,11 +79,12 @@ func humanizeResult2(r resource.TestResult) string {

// Copied from database/sql
var (
outputersMu sync.Mutex
outputers = make(map[string]Outputer)
outputersMu sync.Mutex
outputers = make(map[string]Outputer)
outputerFormatOptions = make(map[string][]string)
)

func RegisterOutputer(name string, outputer Outputer) {
func RegisterOutputer(name string, outputer Outputer, formatOptions []string) {
outputersMu.Lock()
defer outputersMu.Unlock()

Expand All @@ -93,6 +95,7 @@ func RegisterOutputer(name string, outputer Outputer) {
panic("goss: Register called twice for ouputer " + name)
}
outputers[name] = outputer
outputerFormatOptions[name] = formatOptions
}

// Outputers returns a sorted list of the names of the registered outputers.
Expand All @@ -107,6 +110,21 @@ func Outputers() []string {
return list
}

func FormatOptions() []string {
outputersMu.Lock()
defer outputersMu.Unlock()
var list []string
for _, formatOptions := range outputerFormatOptions {
for _, opt := range formatOptions {
if !(util.IsValueInList(opt, list)) {
list = append(list, opt)
}
}
}
sort.Strings(list)
return list
}

func GetOutputer(name string) Outputer {
if _, ok := outputers[name]; !ok {
fmt.Println("goss: Bad output format: " + name)
Expand Down
7 changes: 5 additions & 2 deletions outputs/rspecish.go
Expand Up @@ -6,11 +6,14 @@ import (
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
)

type Rspecish struct{}

func (r Rspecish) Output(w io.Writer, results <-chan []resource.TestResult, startTime time.Time) (exitCode int) {
func (r Rspecish) Output(w io.Writer, results <-chan []resource.TestResult,
startTime time.Time, outConfig util.OutputConfig) (exitCode int) {

testCount := 0
var failedOrSkipped [][]resource.TestResult
var skipped, failed int
Expand Down Expand Up @@ -47,5 +50,5 @@ func (r Rspecish) Output(w io.Writer, results <-chan []resource.TestResult, star
}

func init() {
RegisterOutputer("rspecish", &Rspecish{})
RegisterOutputer("rspecish", &Rspecish{}, []string{})
}
7 changes: 5 additions & 2 deletions outputs/silent.go
Expand Up @@ -5,11 +5,14 @@ import (
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
)

type Silent struct{}

func (r Silent) Output(w io.Writer, results <-chan []resource.TestResult, startTime time.Time) (exitCode int) {
func (r Silent) Output(w io.Writer, results <-chan []resource.TestResult,
startTime time.Time, outConfig util.OutputConfig) (exitCode int) {

var failed int
for resultGroup := range results {
for _, testResult := range resultGroup {
Expand All @@ -27,5 +30,5 @@ func (r Silent) Output(w io.Writer, results <-chan []resource.TestResult, startT
}

func init() {
RegisterOutputer("silent", &Silent{})
RegisterOutputer("silent", &Silent{}, []string{})
}
7 changes: 5 additions & 2 deletions outputs/tap.go
Expand Up @@ -7,11 +7,14 @@ import (
"time"

"github.com/aelsabbahy/goss/resource"
"github.com/aelsabbahy/goss/util"
)

type Tap struct{}

func (r Tap) Output(w io.Writer, results <-chan []resource.TestResult, startTime time.Time) (exitCode int) {
func (r Tap) Output(w io.Writer, results <-chan []resource.TestResult,
startTime time.Time, outConfig util.OutputConfig) (exitCode int) {

testCount := 0
failed := 0

Expand Down Expand Up @@ -49,5 +52,5 @@ func (r Tap) Output(w io.Writer, results <-chan []resource.TestResult, startTime
}

func init() {
RegisterOutputer("tap", &Tap{})
RegisterOutputer("tap", &Tap{}, []string{})
}