diff --git a/asstatusparse.go b/asstatusparse.go new file mode 100644 index 0000000..92d065b --- /dev/null +++ b/asstatusparse.go @@ -0,0 +1,63 @@ +package checkers + +import "strings" + +type invalidStatusMapError string + +func (err invalidStatusMapError) Error() string { + return "invalid status map: " + string(err) +} + +type duplicateStatusMapError Status + +func (err duplicateStatusMapError) Error() string { + return "duplicate status in map: " + Status(err).String() +} + +func parseStatusPrefix(src string) (Status, string, bool) { + switch { + case strings.HasPrefix(src, "OK"): + return OK, src[len("OK"):], true + case strings.HasPrefix(src, "WARNING"): + return WARNING, src[len("WARNING"):], true + case strings.HasPrefix(src, "CRITICAL"): + return CRITICAL, src[len("CRITICAL"):], true + case strings.HasPrefix(src, "UNKNOWN"): + return UNKNOWN, src[len("UNKNOWN"):], true + default: + return OK, src, false + } +} + +// Parse parses a string of the form =. is one of: +// +// - ok +// - warning +// - critical +// - unknown +// +// You can specify multiple key-value pairs separated by commas. +func Parse(src string) (map[Status]Status, error) { + orig, stm := src, map[Status]Status{} + for src = strings.ToUpper(src); src != ""; { + var from, to Status + var ok bool + if from, src, ok = parseStatusPrefix(src); !ok { + return nil, invalidStatusMapError(orig) + } + if src, ok = strings.CutPrefix(src, "="); !ok { + return nil, invalidStatusMapError(orig) + } + if to, src, ok = parseStatusPrefix(src); !ok { + return nil, invalidStatusMapError(orig) + } + if src, ok = strings.CutPrefix(src, ","); ok == (src == "") { + return nil, invalidStatusMapError(orig) + } + if _, ok = stm[from]; ok { + return nil, duplicateStatusMapError(from) + } + stm[from] = to + } + return stm, nil +} diff --git a/asstatusparse_test.go b/asstatusparse_test.go new file mode 100644 index 0000000..6e5643c --- /dev/null +++ b/asstatusparse_test.go @@ -0,0 +1,85 @@ +package checkers + +import ( + "reflect" + "testing" +) + +func TestParse(t *testing.T) { + tests := []struct { + name string + source string + expected map[Status]Status + wantErr bool + }{ + { + name: "normal", + source: "unknown=critical", + expected: map[Status]Status{ + UNKNOWN: CRITICAL, + }, + }, + { + name: "uppercase", + source: "UNKNOWN=CRITICAL", + expected: map[Status]Status{ + UNKNOWN: CRITICAL, + }, + }, + { + name: "multi", + source: "unknown=ok,warning=critical", + expected: map[Status]Status{ + UNKNOWN: OK, + WARNING: CRITICAL, + }, + }, + { + name: "from error", + source: "invalid=critical", + wantErr: true, + }, + { + name: "= error", + source: "unknown critical", + wantErr: true, + }, + { + name: "to error", + source: "critical=invalid", + wantErr: true, + }, + { + name: "argument error", + source: "unknown=critical=invalid", + wantErr: true, + }, + { + name: "missing comma error", + source: "unknown=criticalwarning=critical", + wantErr: true, + }, + { + name: "trailing comma error", + source: "unknown=ok,", + wantErr: true, + }, + { + name: "duplicate error", + source: "critical=unknown,critical=warning", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual, err := Parse(tt.source) + if (err != nil) != tt.wantErr { + t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(tt.expected, actual) { + t.Errorf("Parse() should be %+v but got: %+v", tt.expected, actual) + } + }) + } +} diff --git a/checkers.go b/checkers.go index 57276f2..bf51edb 100644 --- a/checkers.go +++ b/checkers.go @@ -19,11 +19,11 @@ const ( func (st Status) String() string { switch st { - case 0: + case OK: return "OK" - case 1: + case WARNING: return "WARNING" - case 2: + case CRITICAL: return "CRITICAL" default: return "UNKNOWN" @@ -53,6 +53,15 @@ func (ckr *Checker) Exit() { exit(int(ckr.Status)) } +func (ckr *Checker) ExitStatusAs(maps map[Status]Status) { + if _, ok := maps[ckr.Status]; ok { + ckr.Status = maps[ckr.Status] + } + + fmt.Println(ckr.String()) + exit(int(ckr.Status)) +} + func (ckr *Checker) String() string { return fmt.Sprintf("%s %s: %s", ckr.Name, ckr.Status, ckr.Message) } diff --git a/go.mod b/go.mod index be382a8..5eda7de 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/mackerelio/checkers -go 1.18 +go 1.20 diff --git a/go.sum b/go.sum deleted file mode 100644 index e69de29..0000000