Skip to content
This repository was archived by the owner on Nov 14, 2024. It is now read-only.

Commit 5fb3b2b

Browse files
committed
wip
1 parent abfc91e commit 5fb3b2b

File tree

16 files changed

+479
-118
lines changed

16 files changed

+479
-118
lines changed

internal/api/error.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package api
2+
3+
// ErrorResult returns a CheckResult when an error occurs.
4+
func ErrorResult(name string, summary string, err error) *CheckResult {
5+
return &CheckResult{
6+
Name: name,
7+
State: StateFailed,
8+
Summary: summary,
9+
Details: map[string]interface{}{
10+
"error": err,
11+
},
12+
}
13+
}

internal/api/error_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package api_test
2+
3+
import (
4+
"errors"
5+
"testing"
6+
7+
"cdr.dev/slog/sloggers/slogtest/assert"
8+
"github.com/cdr/coder-doctor/internal/api"
9+
)
10+
11+
func TestErrorResult(t *testing.T) {
12+
t.Parallel()
13+
14+
err := errors.New("failed to connect to database")
15+
res := api.ErrorResult("check-name", "check failed", err)
16+
17+
assert.Equal(t, "name matches", "check-name", res.Name)
18+
assert.Equal(t, "state matches", api.StateFailed, res.State)
19+
assert.Equal(t, "summary matches", "check failed", res.Summary)
20+
assert.Equal(t, "error matches", err, res.Details["error"])
21+
}

internal/api/types.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package api
22

33
import (
44
"context"
5+
"fmt"
6+
7+
"golang.org/x/xerrors"
58
)
69

710
type Checker interface {
@@ -19,6 +22,8 @@ type Checker interface {
1922
Run(context.Context) CheckResults
2023
}
2124

25+
var _ = fmt.Stringer(StatePassed)
26+
2227
type CheckState int
2328

2429
const (
@@ -41,6 +46,73 @@ const (
4146
StateSkipped
4247
)
4348

49+
func (s CheckState) MustEmoji() string {
50+
emoji, err := s.Emoji()
51+
if err != nil {
52+
panic(err.Error())
53+
}
54+
return emoji
55+
}
56+
57+
func (s CheckState) Emoji() (string, error) {
58+
switch s {
59+
case StatePassed:
60+
return "✅", nil
61+
case StateWarning:
62+
return "⚠️", nil
63+
case StateFailed:
64+
return "❌", nil
65+
case StateInfo:
66+
return "ℹ️", nil
67+
case StateSkipped:
68+
return "🤔", nil
69+
}
70+
71+
return "", xerrors.Errorf("unknown state: %d", s)
72+
}
73+
74+
func (s CheckState) MustText() string {
75+
text, err := s.Text()
76+
if err != nil {
77+
panic(err.Error())
78+
}
79+
return text
80+
}
81+
82+
func (s CheckState) Text() (string, error) {
83+
switch s {
84+
case StatePassed:
85+
return "PASS", nil
86+
case StateWarning:
87+
return "WARN", nil
88+
case StateFailed:
89+
return "FAIL", nil
90+
case StateInfo:
91+
return "INFO", nil
92+
case StateSkipped:
93+
return "SKIP", nil
94+
}
95+
96+
return "", xerrors.Errorf("unknown state: %d", s)
97+
}
98+
99+
func (s CheckState) String() string {
100+
switch s {
101+
case StatePassed:
102+
return "StatePassed"
103+
case StateWarning:
104+
return "StateWarning"
105+
case StateFailed:
106+
return "StateFailed"
107+
case StateInfo:
108+
return "StateInfo"
109+
case StateSkipped:
110+
return "StateSkipped"
111+
}
112+
113+
panic(fmt.Sprintf("unknown state: %d", s))
114+
}
115+
44116
type CheckResult struct {
45117
Name string
46118
State CheckState

internal/api/types_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package api_test
2+
3+
import (
4+
"testing"
5+
6+
"cdr.dev/slog/sloggers/slogtest/assert"
7+
"github.com/cdr/coder-doctor/internal/api"
8+
)
9+
10+
func TestKnownStates(t *testing.T) {
11+
t.Parallel()
12+
13+
states := []api.CheckState{
14+
api.StatePassed,
15+
api.StateWarning,
16+
api.StateFailed,
17+
api.StateInfo,
18+
api.StateSkipped,
19+
}
20+
21+
for _, state := range states {
22+
t.Run(state.String(), func(t *testing.T) {
23+
emoji, err := state.Emoji()
24+
assert.Success(t, "state.Emoji() error non-nil", err)
25+
assert.True(t, "state.Emoji() is non-empty", len(emoji) > 0)
26+
27+
text, err := state.Text()
28+
assert.Success(t, "state.Text() error non-nil", err)
29+
assert.True(t, "state.Text() is non-empty", len(text) > 0)
30+
31+
str := state.String()
32+
assert.True(t, "state.String() is non-empty", len(str) > 0)
33+
})
34+
}
35+
}

internal/api/util.go

Lines changed: 0 additions & 46 deletions
This file was deleted.

internal/api/writer.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package api
2+
3+
// ResultWriter writes the given result to a configured output.
4+
type ResultWriter interface {
5+
WriteResult(result *CheckResult) error
6+
}
7+
8+
// DiscardWriter is a writer that discards all results.
9+
type DiscardWriter struct {
10+
}
11+
12+
func (*DiscardWriter) WriteResult(result *CheckResult) error {
13+
return nil
14+
}

internal/api/writer_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package api_test
2+
3+
import (
4+
"testing"
5+
6+
"cdr.dev/slog/sloggers/slogtest/assert"
7+
"github.com/cdr/coder-doctor/internal/api"
8+
)
9+
10+
var _ = api.ResultWriter(&api.DiscardWriter{})
11+
12+
func TestDiscardWriter(t *testing.T) {
13+
t.Parallel()
14+
15+
w := &api.DiscardWriter{}
16+
err := w.WriteResult(nil)
17+
18+
assert.Success(t, "discard with nil result", err)
19+
20+
err = w.WriteResult(&api.CheckResult{
21+
Name: "test-check",
22+
State: api.StatePassed,
23+
Summary: "check successful",
24+
})
25+
assert.Success(t, "discard with success result", err)
26+
}

internal/cmd/check/kube/kubernetes.go

Lines changed: 0 additions & 66 deletions
This file was deleted.

internal/cmd/check/kubernetes/kubernetes.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"cdr.dev/slog"
99
"cdr.dev/slog/sloggers/sloghuman"
1010

11-
kclient "k8s.io/client-go/kubernetes"
11+
"k8s.io/client-go/kubernetes"
1212
// Kubernetes authentication plugins
1313
_ "k8s.io/client-go/plugin/pkg/client/auth/azure"
1414
_ "k8s.io/client-go/plugin/pkg/client/auth/exec"
@@ -17,8 +17,8 @@ import (
1717
_ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
1818
"k8s.io/client-go/tools/clientcmd"
1919

20-
"github.com/cdr/coder-doctor/internal/api"
2120
"github.com/cdr/coder-doctor/internal/checks/kube"
21+
"github.com/cdr/coder-doctor/internal/humanwriter"
2222
)
2323

2424
func NewCommand() *cobra.Command {
@@ -78,7 +78,7 @@ func run(cmd *cobra.Command, _ []string) error {
7878
return err
7979
}
8080

81-
clientset, err := kclient.NewForConfig(config)
81+
clientset, err := kubernetes.NewForConfig(config)
8282
if err != nil {
8383
return err
8484
}
@@ -99,6 +99,8 @@ func run(cmd *cobra.Command, _ []string) error {
9999
return err
100100
}
101101

102+
// TODO: this is pretty arbitrary, use a defined verbosity similar to
103+
// kubectl
102104
if verbosity > 5 {
103105
log = log.Leveled(slog.LevelDebug)
104106
}
@@ -109,10 +111,15 @@ func run(cmd *cobra.Command, _ []string) error {
109111
kube.WithLogger(log),
110112
)
111113

114+
writer := humanwriter.New()
115+
112116
results := checker.Run(cmd.Context())
113-
err = api.WriteResults(cmd.OutOrStdout(), results)
114-
if err != nil {
115-
return xerrors.Errorf("failed to write results to stdout: %w", err)
117+
for _, result := range results {
118+
err = writer.WriteResult(result)
119+
if err != nil {
120+
return xerrors.Errorf("failed to write results to stdout: %w", err)
121+
}
122+
116123
}
117124

118125
return nil

0 commit comments

Comments
 (0)