/
cliprinter.go
126 lines (106 loc) · 3.41 KB
/
cliprinter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package cliprinter
import (
"errors"
"io"
commoncli "github.com/spiffe/spire/pkg/common/cli"
"github.com/spiffe/spire/pkg/common/cliprinter/internal/errorjson"
"github.com/spiffe/spire/pkg/common/cliprinter/internal/errorpretty"
"github.com/spiffe/spire/pkg/common/cliprinter/internal/protojson"
"github.com/spiffe/spire/pkg/common/cliprinter/internal/protopretty"
"github.com/spiffe/spire/pkg/common/cliprinter/internal/structjson"
"github.com/spiffe/spire/pkg/common/cliprinter/internal/structpretty"
"google.golang.org/protobuf/proto"
)
// Printer is an interface for providing a printer implementation to
// a CLI utility.
type Printer interface {
PrintError(error) error
PrintProto(...proto.Message) error
PrintStruct(...any) error
}
// CustomPrettyFunc is used to provide a custom function for pretty
// printing messages. The intent is to provide a migration pathway
// for pre-existing CLI code, such that this code can supply a
// custom pretty printer that mirrors its current behavior, but
// still be able to gain formatter functionality for other outputs.
type CustomPrettyFunc func(*commoncli.Env, ...any) error
// ErrInternalCustomPrettyFunc should be returned by a CustomPrettyFunc when some internal error occurs.
var ErrInternalCustomPrettyFunc = errors.New("internal error: cli printer; please report this bug")
type printer struct {
format formatType
env *commoncli.Env
cp CustomPrettyFunc
}
func newPrinter(f formatType, env *commoncli.Env) *printer {
if env == nil {
env = commoncli.DefaultEnv
}
return &printer{
format: f,
env: env,
}
}
// PrintError prints an error and applies the configured formatting.
func (p *printer) PrintError(err error) error {
return p.printError(err)
}
// PrintProto prints a protobuf message and applies the configured formatting.
func (p *printer) PrintProto(msg ...proto.Message) error {
return p.printProto(msg...)
}
// PrintStruct prints a struct and applies the configured formatting.
func (p *printer) PrintStruct(msg ...any) error {
return p.printStruct(msg)
}
func (p *printer) printError(err error) error {
switch p.format {
case json:
return errorjson.Print(err, p.env.Stdout, p.env.Stderr)
default:
return p.printPrettyError(err, p.env.Stdout, p.env.Stderr)
}
}
func (p *printer) printProto(msg ...proto.Message) error {
switch p.format {
case json:
return protojson.Print(msg, p.env.Stdout, p.env.Stderr)
default:
return p.printPrettyProto(msg, p.env.Stdout, p.env.Stderr)
}
}
func (p *printer) printStruct(msg ...any) error {
switch p.format {
case json:
return structjson.Print(msg, p.env.Stdout, p.env.Stderr)
default:
return p.printPrettyStruct(msg, p.env.Stdout, p.env.Stderr)
}
}
func (p *printer) getFormat() formatType {
return p.format
}
func (p *printer) setCustomPrettyPrinter(cp CustomPrettyFunc) {
p.cp = cp
}
func (p *printer) printPrettyError(err error, stdout, stderr io.Writer) error {
if p.cp != nil {
return p.cp(p.env, err)
}
return errorpretty.Print(err, stdout, stderr)
}
func (p *printer) printPrettyProto(msgs []proto.Message, stdout, stderr io.Writer) error {
if p.cp != nil {
m := []any{}
for _, msg := range msgs {
m = append(m, msg.(any))
}
return p.cp(p.env, m...)
}
return protopretty.Print(msgs, stdout, stderr)
}
func (p *printer) printPrettyStruct(msg []any, stdout, stderr io.Writer) error {
if p.cp != nil {
return p.cp(p.env, msg...)
}
return structpretty.Print(msg, stdout, stderr)
}